NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

shipSKINRSceneContainer.py (15633B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\cosmetics\ship\pages\studio\shipSKINRSceneContainer.py
      2 import logging
      3 import blue
      4 import geo2
      5 import trinity
      6 import uthread
      7 import uthread2
      8 from carbon.client.script.environment.AudioUtil import PlaySound
      9 from carbonui.uianimations import animations
     10 from cosmetics.client.ships.skins.live_data import current_skin_design_signals, current_skin_design
     11 from cosmetics.common.ships.skins.static_data.component_category import ComponentCategory
     12 from cosmetics.common.ships.skins.static_data.pattern_attribute import PatternAttribute
     13 from cosmetics.common.ships.skins.static_data.slot_name import SlotID, PATTERN_SLOT_IDS, PATTERN_SLOT_ID_BY_PATTERN_MATERIAL_ID
     14 from eve.client.script.environment.sofService import GetSofService
     15 from eve.client.script.environment.spaceObject.cosmeticsManager import CosmeticsManager
     16 from eve.client.script.environment.spaceObject.spaceObject import modify_dna
     17 from eve.client.script.ui.camera.skinrShipSceneContainerCamera import SkinrShipSceneContainerCamera
     18 from eve.client.script.ui.control.scenecontainer import SceneContainer
     19 from eve.client.script.ui.cosmetics.ship.const import ANIM_DURATION_LONG, ANIM_DURATION_EXTRA_LONG, SkinrPage
     20 from eve.client.script.ui.cosmetics.ship.pages.studio import studioSignals, nebulaConsts
     21 from eve.client.script.ui.cosmetics.ship.pages.studio.patternProjectorGizmo import PatternProjectorGizmo
     22 from eve.client.script.ui.cosmetics.ship.pages.studio.studioUtil import is_green_screen_enabled
     23 from evegraphics import utils as gfxutils
     24 from fsdBuiltData.common.graphicIDs import GetGraphicFile
     25 from cosmetics.client.ships.qa.settings import visualize_shape_ellipsoid
     26 log = logging.getLogger(__name__)
     27 TRANSITION_ZOOM_DEFAULT = 0.5
     28 ZOOM_RANGE = [1.6, 3.6]
     29 SCENE_GRAPHICID = 26811
     30 SHIP_MATERIALIZATION_MULTIEFFECT_GRAPHICID = 27581
     31 SKINR_ENVIRONMENT_VFX_GRAPHICID = 27580
     32 
     33 class ShipSKINRSceneContainer(SceneContainer):
     34     _model_dna = None
     35     _type_id = None
     36 
     37     def __init__(self, **kwargs):
     38         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: Start constructing')
     39         super(ShipSKINRSceneContainer, self).__init__(**kwargs)
     40         self.pattern_projector_gizmo = PatternProjectorGizmo()
     41         self.environment = None
     42         self.shipReplacementMultiEffect = None
     43         self._lastSwapTriggerTimeStamp = 0.0
     44         self.model = None
     45         self.oldModel = None
     46         self._current_skin_design = None
     47         self._load_ship_thread = None
     48         self.PrepareSpaceScene()
     49         if self.camera:
     50             self.camera.farClip = 1000000
     51             self.camera.nearClip = 10
     52         self.cosmetics_manager = CosmeticsManager()
     53         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: Finish constructing')
     54         self.connect_signals()
     55 
     56     def Close(self):
     57         super(ShipSKINRSceneContainer, self).Close()
     58         self.disconnect_signals()
     59 
     60     def connect_signals(self):
     61         current_skin_design_signals.on_component_attribute_changed.connect(self.on_current_design_component_attribute_changed)
     62         current_skin_design_signals.on_pattern_blend_mode_changed.connect(self.on_pattern_blend_mode_changed)
     63         current_skin_design_signals.on_slot_fitting_changed.connect(self.on_slot_fitting_changed)
     64         nebulaConsts.SELECTED_SKINR_BACKGROUND.on_change.connect(self.on_nebula_changed)
     65         visualize_shape_ellipsoid.on_change.connect(self.on_visualize_shape_ellipsoid)
     66         studioSignals.on_page_opened.connect(self.on_page_opened)
     67 
     68     def disconnect_signals(self):
     69         current_skin_design_signals.on_component_attribute_changed.disconnect(self.on_current_design_component_attribute_changed)
     70         current_skin_design_signals.on_pattern_blend_mode_changed.disconnect(self.on_pattern_blend_mode_changed)
     71         current_skin_design_signals.on_slot_fitting_changed.disconnect(self.on_slot_fitting_changed)
     72         nebulaConsts.SELECTED_SKINR_BACKGROUND.on_change.disconnect(self.on_nebula_changed)
     73         studioSignals.on_page_opened.disconnect(self.on_page_opened)
     74 
     75     def on_page_opened(self, page_id, page_args, last_page_id, animate = True):
     76         if nebulaConsts.skinr_nebula_backgrounds_enabled():
     77             if last_page_id is SkinrPage.STUDIO_DESIGNER:
     78                 self.on_nebula_changed(nebulaConsts.BackgroundEnum.Empty)
     79             elif page_id is SkinrPage.STUDIO_DESIGNER:
     80                 self.on_nebula_changed(nebulaConsts.SELECTED_SKINR_BACKGROUND.get())
     81 
     82     def on_visualize_shape_ellipsoid(self, value):
     83         if value is True:
     84             childEffect = trinity.Load('res:/fisfx/utils/ShieldEllipsoidTester.red')
     85             r = self.model.shapeEllipsoidRadius
     86             childEffect.scaling = (r[0] * 2.0, r[1] * 2.0, r[2] * 2.0)
     87             childEffect.translation = self.model.shapeEllipsoidCenter
     88             self.model.effectChildren.append(childEffect)
     89         elif len(self.model.effectChildren) > 0:
     90             self.model.effectChildren.pop()
     91 
     92     def on_slot_fitting_changed(self, slot_id, component_instance):
     93         if component_instance:
     94             data = component_instance.get_component_data()
     95             if data:
     96                 self._play_apply_sound(data.category)
     97         self.cosmetics_manager.apply_component(slot_id, component_instance)
     98 
     99     def on_nebula_changed(self, value):
    100         if not nebulaConsts.skinr_nebula_backgrounds_enabled() and value is not nebulaConsts.BackgroundEnum.Empty:
    101             return
    102         res_path = nebulaConsts.SKINR_NEBULA_RES_PATHS[value]
    103         self.scene.backgroundEffect.resources.FindByName('AlphaMap').resourcePath = res_path[:-4] + '_refl.dds'
    104         self.scene.backgroundEffect.resources.FindByName('NebulaMap').resourcePath = res_path
    105         self.scene.envMapResPath = res_path[:-4] + '_refl.dds'
    106         self.scene.envMap1ResPath = res_path
    107         self.scene.envMap2ResPath = res_path[:-4] + '_blur.dds'
    108         self.scene.backgroundRenderingEnabled = value is not nebulaConsts.BackgroundEnum.Empty
    109         self.environment.display = value is nebulaConsts.BackgroundEnum.Empty
    110 
    111     def _play_apply_sound(self, category):
    112         if category == ComponentCategory.MATERIAL:
    113             PlaySound('nanocoating_button_select_color_play')
    114         elif category == ComponentCategory.METALLIC:
    115             PlaySound('nanocoating_button_push_detailing_play')
    116         elif category == ComponentCategory.PATTERN:
    117             PlaySound('nanocoating_button_select_pattern_play')
    118 
    119     def on_pattern_blend_mode_changed(self, value):
    120         self.cosmetics_manager.SetBlendMode(self.model, value)
    121 
    122     def on_current_design_component_attribute_changed(self, slot_id, attribute_id, value):
    123         if slot_id not in PATTERN_SLOT_IDS:
    124             return
    125         if attribute_id == PatternAttribute.MIRROR:
    126             self.cosmetics_manager.SetMirroredState(slot_id, value)
    127         elif attribute_id == PatternAttribute.PROJECT_TO_AREA_1:
    128             self.cosmetics_manager.SetTargetMaterialArea(slot_id, SlotID.PRIMARY_NANOCOATING, value)
    129         elif attribute_id == PatternAttribute.PROJECT_TO_AREA_2:
    130             self.cosmetics_manager.SetTargetMaterialArea(slot_id, SlotID.SECONDARY_NANOCOATING, value)
    131         elif attribute_id == PatternAttribute.PROJECT_TO_AREA_3:
    132             self.cosmetics_manager.SetTargetMaterialArea(slot_id, SlotID.TERTIARY_NANOCOATING, value)
    133         elif attribute_id == PatternAttribute.PROJECT_TO_AREA_4:
    134             self.cosmetics_manager.SetTargetMaterialArea(slot_id, SlotID.TECH_AREA, value)
    135         elif attribute_id == PatternAttribute.SCALE:
    136             self.cosmetics_manager.ApplyScaling(slot_id, value)
    137         elif attribute_id == PatternAttribute.ROTATION:
    138             self.cosmetics_manager.ApplyRotation(slot_id, value)
    139         elif attribute_id == PatternAttribute.POSITION:
    140             self.cosmetics_manager.ApplyTranslation(slot_id, value)
    141 
    142     def PrepareCamera(self):
    143         self.camera = SkinrShipSceneContainerCamera()
    144         self.camera.OnActivated()
    145 
    146     def turn_camera(self, yaw, pitch, duration):
    147         self.camera.StopUpdateThreads()
    148         self.camera.StopAnimations()
    149         animations.MorphScalar(self.camera, 'yaw', self.camera.yaw, yaw, duration=duration)
    150         animations.MorphScalar(self.camera, 'pitch', self.camera.pitch, pitch, duration=duration)
    151 
    152     def rotate_ship_in(self, duration):
    153         q1 = geo2.QuaternionRotationSetYawPitchRoll(-0.1, -0.05, 0.0)
    154         q2 = geo2.QuaternionRotationSetYawPitchRoll(0.0, 0.0, 0.0)
    155         animations.MorphQuaternion(self.model.rotationCurve, 'value', q1, q2, duration)
    156 
    157     def SetPattern(self, pattern_id):
    158         self.cosmetics_manager.SetProjectionTexture(pattern_id)
    159 
    160     def GetCurrentShip(self):
    161         return self.model
    162 
    163     def GetCurrentCamera(self):
    164         return self.camera
    165 
    166     def PrepareSpaceScene(self, scenePath = None):
    167         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: PrepareSpaceScene started')
    168         if scenePath is None:
    169             scenePath = GetGraphicFile(SCENE_GRAPHICID)
    170         super(ShipSKINRSceneContainer, self).PrepareSpaceScene(scenePath=scenePath)
    171         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: PrepareSpaceScene prepared base scene')
    172         if not self.scene:
    173             return
    174         if not self.scene.postprocess:
    175             self.scene.postprocess = trinity.Tr2PostProcess2()
    176         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: PrepareSpaceScene added postprocess')
    177         if not is_green_screen_enabled():
    178             environmentResourcePath = GetGraphicFile(SKINR_ENVIRONMENT_VFX_GRAPHICID)
    179             self.environment = blue.resMan.LoadObject(environmentResourcePath)
    180             if self.environment is not None:
    181                 self.AddToScene(self.environment, clear=0)
    182             self.environment.StartControllers()
    183         else:
    184             self.renderJob.GetStep('CLEAR').color = (0, 1, 0, 0)
    185         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: PrepareSpaceScene added environment')
    186         multiEffectResourcePath = GetGraphicFile(SHIP_MATERIALIZATION_MULTIEFFECT_GRAPHICID)
    187         sme = blue.resMan.LoadObject(multiEffectResourcePath)
    188         self.shipReplacementMultiEffect = sme
    189         if self.shipReplacementMultiEffect is not None:
    190             self.AddToScene(self.shipReplacementMultiEffect, clear=0)
    191             if self.environment is not None:
    192                 self.shipReplacementMultiEffect.SetParameter('skinrEnv', self.environment)
    193             self.shipReplacementMultiEffect.SetControllerVariable('object_materialize', 0.0)
    194             self.shipReplacementMultiEffect.StartControllers()
    195         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: PrepareSpaceScene added ship replacement multieffect')
    196         if self.pattern_projector_gizmo is not None and self.scene:
    197             self.pattern_projector_gizmo.load_and_place_in_scene(self.scene)
    198         log.info('SKIN PREVIEW - PaintPreviewSceneContainer: PrepareSpaceScene finished')
    199 
    200     def preview_type(self, type_id, skinDesign = None, animate = True):
    201         log.info('SKIN PREVIEW - Preview: commanded preview for type: {type_id}'.format(type_id=type_id))
    202         model_dna = modify_dna(base_dna=gfxutils.BuildSOFDNAFromTypeID(type_id), patternMat1='green_lime_emissive', patternName='cosm_blank_projection')
    203         type_changed = type_id != self._type_id
    204         self._type_id = type_id
    205         self._model_dna = model_dna
    206         if skinDesign:
    207             self._current_skin_design = skinDesign
    208         if animate or type_changed:
    209             self._animate_model_swap()
    210         else:
    211             trinity.WaitForResourceLoads()
    212             self.cosmetics_manager.apply_design(self._current_skin_design)
    213 
    214     def _animate_model_swap(self):
    215         if self._load_ship_thread:
    216             self._lastSwapTriggerTimeStamp = blue.os.GetSimTime()
    217         else:
    218             PlaySound('nanocoating_ship_paint2_play')
    219             if self.shipReplacementMultiEffect is not None:
    220                 self.shipReplacementMultiEffect.SetControllerVariable('object_materialize', 0.0)
    221             log.info('SKIN PREVIEW - Preview: queued delayed load')
    222             self._load_ship_thread = uthread.new(self._load_ship_async)
    223 
    224     def _load_ship_async(self):
    225         try:
    226             self._lastSwapTriggerTimeStamp = blue.os.GetSimTime()
    227             SECOND = 10000000.0
    228             timeUntilReveal = SECOND * ANIM_DURATION_LONG
    229             while self._lastSwapTriggerTimeStamp + timeUntilReveal > blue.os.GetSimTime():
    230                 uthread2.Sleep(0.15)
    231 
    232         finally:
    233             if self.destroyed:
    234                 return
    235             self._load_ship()
    236             trinity.WaitForResourceLoads()
    237             self._swap_out_old_ship()
    238             self._load_ship_thread = None
    239             log.info('SKIN PREVIEW - Preview: delayed load removed from queue')
    240 
    241     def _load_ship(self):
    242         log.info('SKIN PREVIEW - Preview: load started for type {type_id}'.format(type_id=self._type_id))
    243         if self.destroyed:
    244             return
    245         space_object_factory = GetSofService().spaceObjectFactory
    246         self.model = space_object_factory.BuildFromDNA(self._model_dna)
    247         self.model.rotationCurve = trinity.Tr2RotationAdapter()
    248         self.cosmetics_manager.SetTypeID(self._type_id)
    249         self.cosmetics_manager.SetModel(self.model)
    250         self.cosmetics_manager.apply_design(self._current_skin_design)
    251         self.model.SetControllerVariable('boosterOn', 1.0)
    252         log.info('SKIN PREVIEW - Preview: model set for type {type_id}'.format(type_id=self._type_id))
    253         while len(self.model.observers) > 0:
    254             self.model.observers.pop()
    255 
    256         self.model.FreezeHighDetailMesh()
    257         if hasattr(self.model, 'dirtLevel'):
    258             self.model.dirtLevel = -1.5
    259         log.info('SKIN PREVIEW - Preview: load finished for type {type_id}'.format(type_id=self._type_id))
    260 
    261     def _swap_out_old_ship(self):
    262         log.info('SKIN PREVIEW - SwapOutOldShip: started')
    263         if self.destroyed:
    264             return
    265         if self.oldModel is not None and self.oldModel in self.scene.objects:
    266             self.scene.objects.remove(self.oldModel)
    267         log.info('SKIN PREVIEW - SwapOutOldShip: Old Model removed')
    268         if self.scene and self.model is not None:
    269             self.scene.objects.append(self.model)
    270         log.info('SKIN PREVIEW - SwapOutOldShip: model added to scene')
    271         self._fit_model_in_view(self.model)
    272         log.info('SKIN PREVIEW - SwapOutOldShip: model fit in view')
    273         if self.shipReplacementMultiEffect is not None:
    274             self.shipReplacementMultiEffect.SetParameter('skinrAsset', self.model)
    275             self.shipReplacementMultiEffect.StartControllers()
    276             self.shipReplacementMultiEffect.SetControllerVariable('object_materialize', 1.0)
    277         log.info('SKIN PREVIEW - SwapOutOldShip: replacement multieffect applied')
    278         self.model.StartControllers()
    279         self.oldModel = self.model
    280         self.rotate_ship_in(ANIM_DURATION_EXTRA_LONG)
    281         log.info('SKIN PREVIEW - SwapOutOldShip: finished')
    282 
    283     def _fit_model_in_view(self, model):
    284         if model is None or not self.camera:
    285             return
    286         rad = model.GetBoundingSphereRadius()
    287         maxRenderDist = self.camera.farClip or 400000.0
    288         min_zoom = ZOOM_RANGE[0] * rad
    289         max_zoom = min(ZOOM_RANGE[1] * rad, maxRenderDist - 2 * rad)
    290         self.SetMinMaxZoom(min_zoom, max_zoom)
    291         self.SetZoom(TRANSITION_ZOOM_DEFAULT)
    292         self.camera.SetInnerBoundRadius(self.model.shapeEllipsoidRadius)
    293         self.camera.SetModelCenter(self.model.shapeEllipsoidCenter)