scriptedlightbase.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /*
  2. Please remember that:
  3. -Lights work only on client side!
  4. -Lights with Brightness or Radius of 0 (or less) are automatically deleted
  5. -Lights are very performance heavy. Especially if they cast shadows. Use them carefully!
  6. Script author: Boris Vacula
  7. */
  8. class ScriptedLightBase extends EntityLightSource
  9. {
  10. float m_LifetimeStart;
  11. float m_LifetimeEnd = -1; // -1 makes this light permanent
  12. float m_FadeOutTime = -1;
  13. float m_FadeInTime = -1;
  14. float m_Radius;
  15. float m_RadiusTarget;
  16. float m_Brightness;
  17. float m_BrightnessPulse; // flicker effect
  18. float m_BrightnessPulseSpeed;
  19. float m_BrightnessPulseAmplitudeMax;
  20. float m_BrightnessPulseAmplitudeMin;
  21. float m_BrightnessTarget;
  22. float m_BrightnessSpeedOfChange = 1;
  23. float m_RadiusSpeedOfChange = 1;
  24. float m_OptimizeShadowsRadius = 0; // Within this range between the light source and camera the shadows will be automatically disabled to save on performance
  25. float m_DancingShadowsAmplitude;
  26. float m_DancingShadowsSpeed;
  27. float m_BlinkingSpeed;
  28. bool m_IsDebugEnabled = false;
  29. Object m_Parent; // Attachment parent
  30. vector m_LocalPos; // Local position to my attachment parent
  31. vector m_LocalOri; // Local orientation to my attachment parent
  32. vector m_DancingShadowsLocalPos;
  33. ref Timer m_DeleteTimer;
  34. static ref set<ScriptedLightBase> m_NightTimeOnlyLights = new set<ScriptedLightBase>();
  35. //! Constructor. Everything here is executed before the constructor of all children.
  36. void ScriptedLightBase()
  37. {
  38. m_LifetimeStart = GetGame().GetTime();
  39. SetEnabled(true);
  40. SetEventMask(EntityEvent.FRAME);
  41. SetEventMask(EntityEvent.INIT);
  42. }
  43. void ~ScriptedLightBase()
  44. {
  45. if (m_NightTimeOnlyLights)
  46. {
  47. int index = m_NightTimeOnlyLights.Find(this);
  48. if (index != -1)
  49. {
  50. m_NightTimeOnlyLights.Remove(index);
  51. }
  52. }
  53. }
  54. override void EOnInit(IEntity other, int extra)
  55. {
  56. if (!IsVisibleDuringDaylight())
  57. {
  58. PlayerBase player = PlayerBase.Cast(GetGame().GetPlayer());
  59. if (player && player.m_UndergroundPresence)
  60. SetVisibleDuringDaylight(true);
  61. m_NightTimeOnlyLights.Insert(this);
  62. }
  63. }
  64. override bool IsScriptedLight()
  65. {
  66. return true;
  67. }
  68. void UpdateMode()
  69. {
  70. ItemBase item = ItemBase.Cast(m_Parent);
  71. if (item)
  72. {
  73. InventoryLocation il = new InventoryLocation;
  74. item.GetInventory().GetCurrentInventoryLocation( il );
  75. string slotName;
  76. if (il.GetType() == InventoryLocationType.GROUND)
  77. {
  78. slotName = "Ground";
  79. }
  80. else if (il.GetSlot() != -1)
  81. {
  82. slotName = InventorySlots.GetSlotName(il.GetSlot());
  83. }
  84. UpdateLightMode(slotName);
  85. }
  86. }
  87. private void UpdateLightMode(string slotName);
  88. //! Correct way of deleting light from memory. It is necesarry to have this delay due to hierarchy.
  89. private void DeleteLightWithDelay()
  90. {
  91. DetachFromParent(); // This is the reason for the delay
  92. if (GetGame())
  93. {
  94. if (!m_DeleteTimer)
  95. m_DeleteTimer = new Timer( CALL_CATEGORY_SYSTEM );
  96. m_DeleteTimer.Run( 0.03 , this, "DeleteLightNow", NULL, true);
  97. }
  98. }
  99. // Deletes light now. Do not call this directly. Call Destroy() instead. Otherwise you might get errors related to hierarchy.
  100. private void DeleteLightNow()
  101. {
  102. GetGame().ObjectDelete(this);
  103. }
  104. //! Attaches this light on the parent entity, with optional position and orientation offset.
  105. void AttachOnObject(Object parent, vector local_pos = "0 0 0", vector local_ori = "0 0 0")
  106. {
  107. if (!parent)
  108. {
  109. if (m_Parent)
  110. {
  111. m_Parent.RemoveChild(this);
  112. }
  113. return;
  114. }
  115. else
  116. {
  117. if (m_Parent)
  118. {
  119. m_Parent.RemoveChild(this);
  120. }
  121. }
  122. m_Parent = parent;
  123. m_LocalPos = local_pos;
  124. m_LocalOri = local_ori;
  125. SetOrientation(local_ori);
  126. SetPosition(local_pos);
  127. parent.AddChild(this, -1);
  128. parent.Update();
  129. }
  130. //! Returns attachment parent
  131. Object GetAttachmentParent()
  132. {
  133. return m_Parent;
  134. }
  135. //! Attaches this light on the parent entity's memory point, with optional direction target memory point.
  136. void AttachOnMemoryPoint(Object parent, string memory_point_start, string memory_point_target = "")
  137. {
  138. if (parent.MemoryPointExists(memory_point_start))
  139. {
  140. m_LocalPos = parent.GetMemoryPointPos(memory_point_start);
  141. vector local_ori;
  142. if (memory_point_target != "" )
  143. {
  144. if (parent.MemoryPointExists(memory_point_target))
  145. {
  146. vector target_pos = parent.GetSelectionPositionLS(memory_point_target);
  147. target_pos = vector.Direction(m_LocalPos, target_pos);
  148. local_ori = target_pos.VectorToAngles();
  149. }
  150. else
  151. {
  152. ErrorEx("memory point 'memory_point_target' not found when attaching light");
  153. }
  154. }
  155. AttachOnObject(parent, m_LocalPos, local_ori);
  156. UpdateMode();
  157. }
  158. else
  159. {
  160. ErrorEx("memory point 'memory_point_start' not found when attaching light");
  161. }
  162. }
  163. //! Detaches this light from its parent entity.
  164. void DetachFromParent()
  165. {
  166. if (!m_Parent)
  167. {
  168. m_Parent = Object.Cast( GetParent() );
  169. }
  170. if (m_Parent)
  171. {
  172. if ( !m_Parent.ToDelete() && !ToDelete() )
  173. {
  174. m_Parent.RemoveChild(this);
  175. }
  176. }
  177. m_Parent = null;
  178. m_LocalPos = Vector(0,0,0);
  179. m_LocalOri = Vector(0,0,0);
  180. }
  181. static ScriptedLightBase CreateLightAtObjMemoryPoint(typename name, notnull Object target, string memory_point_start, string memory_point_target = "", vector global_pos = "0 0 0", float fade_in_time_in_s = 0)
  182. {
  183. ScriptedLightBase light;
  184. if (target.MemoryPointExists(memory_point_start))
  185. {
  186. light = CreateLight(name, global_pos, fade_in_time_in_s);
  187. light.AttachOnMemoryPoint(target, memory_point_start, memory_point_target);
  188. }
  189. return light;
  190. }
  191. //! Creates an instance of light on the given position. Optionally, use fade_in_time_in_s parameter to make the light fade into existence.
  192. static ScriptedLightBase CreateLight(typename name, vector global_pos = "0 0 0", float fade_in_time_in_s = 0)
  193. {
  194. ScriptedLightBase light_instance;
  195. if ( !GetGame().IsServer() || !GetGame().IsMultiplayer() ) // Client side
  196. {
  197. light_instance = ScriptedLightBase.Cast( GetGame().CreateObject(name.ToString(), global_pos, true) );
  198. if (!light_instance)
  199. {
  200. Error("Error! Light entity of name " + name.ToString() + " cannot be spawned! This name is incorrect or not inherited from ScriptedLightBase." );
  201. return null;
  202. }
  203. if (fade_in_time_in_s != 0)
  204. {
  205. light_instance.FadeIn(fade_in_time_in_s);
  206. }
  207. }
  208. else // Server side
  209. {
  210. if ( GetGame().IsDebug() )
  211. {
  212. Error("An instance of ScriptedLightBase was attempted to spawn on server side! Lights are CLIENT SIDE ONLY!");
  213. }
  214. }
  215. return light_instance;
  216. }
  217. //! Sets the brightness of the light
  218. void SetBrightnessTo(float value)
  219. {
  220. m_Brightness = value;
  221. m_BrightnessTarget = value;
  222. SetBrightness(m_Brightness * m_BrightnessPulse);
  223. CorrectLightPulseDuringDaylight();
  224. }
  225. //! Call this after using SetBrightness(...) to fix light's intensity during daytime
  226. void CorrectLightPulseDuringDaylight()
  227. {
  228. if (m_Brightness < 100)
  229. {
  230. float v = m_Brightness * 0.01;
  231. if (v > 0)
  232. {
  233. float brightness_compesation = 1 / v;
  234. float compenset_brightness = (m_Brightness * m_BrightnessPulse) * brightness_compesation;
  235. SetBrightness(compenset_brightness);
  236. SetPulseCoef(v);
  237. }
  238. }
  239. else
  240. {
  241. SetPulseCoef(1);
  242. }
  243. }
  244. //! Fades the brightness of the light to the given value.
  245. void FadeBrightnessTo( float value, float time_in_s )
  246. {
  247. m_BrightnessTarget = value;
  248. if (time_in_s == 0)
  249. {
  250. m_BrightnessSpeedOfChange = 9999;
  251. }
  252. else
  253. {
  254. m_BrightnessSpeedOfChange = Math.AbsFloat(m_Brightness - m_BrightnessTarget) / time_in_s;
  255. }
  256. }
  257. //! Sets the radius of the light
  258. void SetRadiusTo(float value)
  259. {
  260. m_Radius = value;
  261. m_RadiusTarget = value;
  262. SetRadius(m_Radius);
  263. }
  264. //! Fades the radius of the light to the given value.
  265. void FadeRadiusTo( float value, float time_in_s )
  266. {
  267. m_RadiusTarget = value;
  268. if (time_in_s == 0)
  269. {
  270. m_RadiusSpeedOfChange = 9999;
  271. }
  272. else
  273. {
  274. m_RadiusSpeedOfChange = Math.AbsFloat(m_Radius - m_RadiusTarget) / time_in_s;
  275. }
  276. }
  277. //! Switches off the light and deletes it from memory
  278. void Destroy()
  279. {
  280. ClearEventMask(EntityEvent.FRAME);
  281. SetEnabled(false);
  282. if (m_Parent)
  283. DeleteLightWithDelay();
  284. else
  285. DeleteLightNow();
  286. }
  287. //! Makes the light destroy itself after the given time in seconds. The light will fade out if it's set to do so with SetFadeOutTime(...)
  288. void SetLifetime(float life_in_s)
  289. {
  290. if(GetGame())
  291. m_LifetimeEnd = GetGame().GetTime() + life_in_s * 1000;
  292. }
  293. //! Sets the fade out time in seconds. Fade out begins automatically as the light nears the end of its life time, or when method FadeOut() is called.
  294. void SetFadeOutTime(float time_in_s)
  295. {
  296. m_FadeOutTime = time_in_s * 1000;
  297. }
  298. //! Starts the fade out process and destroys the light when its done. Optional parameter allows you to set time of this fade out in seconds. If not set, then default value (from SetFadeOutTime(...)) is used.
  299. void FadeOut(float time_in_s = -1)
  300. {
  301. float time_in_ms = time_in_s * 1000;
  302. if (time_in_s == -1)
  303. {
  304. float kill_time_in_s = m_FadeOutTime*0.001;
  305. FadeBrightnessTo(0, kill_time_in_s);
  306. FadeRadiusTo(0, kill_time_in_s);
  307. SetLifetime(kill_time_in_s);
  308. }
  309. else
  310. {
  311. FadeBrightnessTo(0, time_in_s);
  312. FadeRadiusTo(0, time_in_s);
  313. SetLifetime(time_in_s);
  314. }
  315. }
  316. //! Makes the light fade into existence. Works only at the moment the light is created. Consider using FadeBrightnessTo(...) and FadeRadiusTo(...) at anytime later during lifetime.
  317. void FadeIn(float time_in_s)
  318. {
  319. float brightness = m_Brightness;
  320. SetBrightnessTo(0);
  321. FadeBrightnessTo(brightness, time_in_s);
  322. }
  323. //! Prolongs the lifetime of the light in seconds. Use negative number to shorten its lifetime.
  324. void AddLifetime(float life_in_s)
  325. {
  326. m_LifetimeEnd += life_in_s * 1000;
  327. }
  328. //! Override this for custom functionality
  329. void OnFrameLightSource(IEntity other, float timeSlice)
  330. {
  331. // ...
  332. }
  333. //! On frame event. If you want to control your light within your own rules then override the event OnFrameLightSource and put your code there.
  334. override void EOnFrame(IEntity other, float timeSlice)
  335. {
  336. // Control lifetime of the light
  337. int current_time = GetGame().GetTime();
  338. if ( CheckLifetime(current_time) )
  339. {
  340. SetRadius(m_Radius);
  341. }
  342. else
  343. {
  344. return;
  345. }
  346. HandleFlickering(current_time - m_LifetimeStart, timeSlice);
  347. HandleDancingShadows(current_time - m_LifetimeStart, timeSlice);
  348. CheckFadeOut(current_time);
  349. HandleBrightnessFadeing(timeSlice);
  350. HandleRadiusFadeing(timeSlice);
  351. CheckIfParentIsInCargo();
  352. TryShadowOptimization();
  353. OnFrameLightSource(other, timeSlice);
  354. HandleBlinking(current_time);
  355. }
  356. //! Sets the maximum range of the point light within the dancing shadows effect
  357. void SetDancingShadowsAmplitude(float max_deviation_in_meters)
  358. {
  359. m_DancingShadowsAmplitude = Math.AbsFloat(max_deviation_in_meters);
  360. }
  361. //! Sets the maximum speed of the point light within the dancing shadows effect
  362. void SetDancingShadowsMovementSpeed(float speed_in_meters_per_frame)
  363. {
  364. m_DancingShadowsSpeed = Math.AbsFloat(speed_in_meters_per_frame);
  365. }
  366. //! Returns max movement range of pointlight within the dancing shadow effect
  367. float GetDancingShadowsAmplitude()
  368. {
  369. return m_DancingShadowsAmplitude;
  370. }
  371. //! Returns max movement speed of pointlight within the dancing shadow effect
  372. float GetDancingShadowsMovementSpeed()
  373. {
  374. return m_DancingShadowsSpeed;
  375. }
  376. //! Enables some debug functionality of this light
  377. void EnableDebug(bool state)
  378. {
  379. m_IsDebugEnabled = state;
  380. }
  381. // Handles subtle movement of the light point to create the effect of dancing shadows
  382. void HandleDancingShadows(float time, float timeSlice)
  383. {
  384. if (m_DancingShadowsAmplitude > 0)
  385. {
  386. for (int i = 0; i < 3; i++ )
  387. {
  388. m_DancingShadowsLocalPos[i] = m_DancingShadowsLocalPos[i] + ( Math.RandomFloat(-m_DancingShadowsSpeed,m_DancingShadowsSpeed) * timeSlice) ;
  389. if (m_DancingShadowsLocalPos[i] > m_DancingShadowsAmplitude)
  390. m_DancingShadowsLocalPos[i] = m_DancingShadowsAmplitude;
  391. if (m_DancingShadowsLocalPos[i] < -m_DancingShadowsAmplitude)
  392. m_DancingShadowsLocalPos[i] = -m_DancingShadowsAmplitude;
  393. }
  394. if (m_Parent && !m_Parent.ToDelete())
  395. {
  396. // In order to move with the light, it must be detached from its parent first
  397. m_Parent.RemoveChild(this);
  398. SetPosition(m_LocalPos + m_DancingShadowsLocalPos);
  399. m_Parent.AddChild(this, -1);
  400. m_Parent.Update();
  401. }
  402. if (m_IsDebugEnabled)
  403. {
  404. Particle p = ParticleManager.GetInstance().PlayInWorld( ParticleList.DEBUG_DOT, GetPosition() );
  405. p.SetParticleParam( EmitorParam.SIZE, 0.01);
  406. }
  407. }
  408. else
  409. {
  410. m_DancingShadowsLocalPos = Vector(0,0,0);
  411. }
  412. }
  413. // Updates flickering light
  414. void HandleFlickering(float time, float timeSlice)
  415. {
  416. if (m_BrightnessPulseAmplitudeMax > 0)
  417. {
  418. m_BrightnessPulse += ( Math.RandomFloat(-m_BrightnessPulseSpeed, m_BrightnessPulseSpeed) ) * timeSlice;
  419. if (m_BrightnessPulse < m_BrightnessPulseAmplitudeMin + 1)
  420. m_BrightnessPulse = m_BrightnessPulseAmplitudeMin + 1;
  421. if (m_BrightnessPulse > m_BrightnessPulseAmplitudeMax + 1)
  422. m_BrightnessPulse = m_BrightnessPulseAmplitudeMax + 1;
  423. }
  424. else
  425. {
  426. m_BrightnessPulse = 1;
  427. }
  428. }
  429. //! Sets speed of light flickering (random brightness coefficient change per second)
  430. void SetFlickerSpeed(float speed)
  431. {
  432. m_BrightnessPulseSpeed = speed;
  433. }
  434. //! Sets the change coefficient of flickering light. (0.0 - 1.0 values, result of greater values are period time of light off )
  435. void SetFlickerAmplitude(float coef)
  436. {
  437. m_BrightnessPulseAmplitudeMax = Math.AbsFloat(coef);
  438. m_BrightnessPulseAmplitudeMin = -Math.AbsFloat(coef);
  439. }
  440. void SetFlickerAmplitudeMax(float coef)
  441. {
  442. m_BrightnessPulseAmplitudeMax = coef;
  443. }
  444. void SetFlickerAmplitudeMin(float coef)
  445. {
  446. m_BrightnessPulseAmplitudeMin = coef;
  447. }
  448. //! Returns flicker speed
  449. float GetFlickerSpeed()
  450. {
  451. return m_BrightnessPulseSpeed;
  452. }
  453. //! Returns flicker amplitude maximum
  454. float GetFlickerAmplitudeCoefMax()
  455. {
  456. return m_BrightnessPulseAmplitudeMax;
  457. }
  458. //! Returns flicker amplitude minimum
  459. float GetFlickerAmplitudeCoefMin()
  460. {
  461. return m_BrightnessPulseAmplitudeMin;
  462. }
  463. //! Optimizes shadows by disabling them on this light source while it's within the given radius around the camera.
  464. void TryShadowOptimization()
  465. {
  466. if (m_OptimizeShadowsRadius > 0)
  467. {
  468. float distance_to_camera = vector.Distance( GetPosition(), GetGame().GetCurrentCameraPosition() );
  469. if (distance_to_camera < m_OptimizeShadowsRadius)
  470. {
  471. SetCastShadow(false);
  472. }
  473. else
  474. {
  475. SetCastShadow(true);
  476. }
  477. }
  478. }
  479. //! When the light source gets within this radius (radius_in_m) around the camera, then it's shadows are disabled.
  480. void SetDisableShadowsWithinRadius(float radius_in_m)
  481. {
  482. m_OptimizeShadowsRadius = radius_in_m;
  483. }
  484. //! Returns the range you put inside SetDisableShadowsWithinRadius(...)
  485. float GetDisableShadowsWithinRadius()
  486. {
  487. return m_OptimizeShadowsRadius;
  488. }
  489. void CheckIfParentIsInCargo()
  490. {
  491. // TO DO: OPTIMIZE AND REFACTOR! THIS MUST BE HANDLED IN AN EVENT, NOT PER FRAME!
  492. if (m_Parent)
  493. {
  494. EntityAI parent_EAI = EntityAI.Cast( m_Parent );
  495. if (parent_EAI) // Check if the Cast was successfull
  496. {
  497. GameInventory GI = parent_EAI.GetInventory();
  498. if (GI) // Prevents handling of light on the parent item when it's projected in inventory as the item in inventory character's hands.
  499. {
  500. bool is_in_cargo = GI.IsInCargo();
  501. if (!is_in_cargo)
  502. {
  503. EntityAI parent2 = parent_EAI.GetHierarchyParent();
  504. if (parent2 && parent2.GetInventory())
  505. {
  506. is_in_cargo = parent2.GetInventory().IsInCargo();
  507. }
  508. }
  509. if ( is_in_cargo )
  510. {
  511. SetEnabled(false);
  512. }
  513. else
  514. {
  515. SetEnabled(true);
  516. }
  517. }
  518. }
  519. }
  520. }
  521. // Destroys this light if it's past it lifetime
  522. private bool CheckLifetime(int current_time)
  523. {
  524. if ( current_time > m_LifetimeEnd && m_LifetimeEnd != -1 )
  525. {
  526. Destroy();
  527. return false;
  528. }
  529. return true;
  530. }
  531. // Handles fade out effect at the end of lifetime
  532. private void CheckFadeOut( int current_time)
  533. {
  534. // Control fade out of the light
  535. if ( m_FadeOutTime != -1 && m_LifetimeEnd != -1 && current_time > m_LifetimeEnd - m_FadeOutTime )
  536. {
  537. m_FadeOutTime = -1;
  538. m_FadeInTime = -1; // Stop fade in process
  539. float time_left_in_s = (m_LifetimeEnd - current_time) * 0.001;
  540. FadeBrightnessTo(0, time_left_in_s);
  541. FadeRadiusTo(0, time_left_in_s);
  542. }
  543. }
  544. // handles fading of brightness
  545. private void HandleBrightnessFadeing(float timeSlice)
  546. {
  547. if ( m_Brightness != m_BrightnessTarget )
  548. {
  549. float brightness_difference = m_Brightness - m_BrightnessTarget;
  550. if (brightness_difference > m_BrightnessSpeedOfChange*timeSlice)
  551. brightness_difference = m_BrightnessSpeedOfChange*timeSlice;
  552. if (brightness_difference < -m_BrightnessSpeedOfChange*timeSlice)
  553. brightness_difference = -m_BrightnessSpeedOfChange*timeSlice;
  554. m_Brightness -= brightness_difference;
  555. if ( m_Brightness > 0 || m_BrightnessTarget > 0)
  556. {
  557. SetBrightness(m_Brightness * m_BrightnessPulse);
  558. CorrectLightPulseDuringDaylight();
  559. }
  560. else
  561. {
  562. Destroy();
  563. return;
  564. }
  565. }
  566. else
  567. {
  568. SetBrightness(m_Brightness * m_BrightnessPulse);
  569. CorrectLightPulseDuringDaylight();
  570. }
  571. }
  572. // handles fading of radius
  573. private void HandleRadiusFadeing(float timeSlice)
  574. {
  575. if ( m_Radius != m_RadiusTarget )
  576. {
  577. float radius_difference = m_Radius - m_RadiusTarget;
  578. if (radius_difference > m_RadiusSpeedOfChange*timeSlice)
  579. radius_difference = m_RadiusSpeedOfChange*timeSlice;
  580. if (radius_difference < -m_RadiusSpeedOfChange*timeSlice)
  581. radius_difference = -m_RadiusSpeedOfChange*timeSlice;
  582. m_Radius -= radius_difference;
  583. if ( m_Radius > 0 || m_RadiusTarget > 0)
  584. {
  585. SetRadius(m_Radius);
  586. }
  587. else
  588. {
  589. Destroy();
  590. return;
  591. }
  592. }
  593. else
  594. {
  595. SetRadius(m_Radius);
  596. }
  597. }
  598. //! Sets blinking speed (no blinking if speed <= 0)
  599. void SetBlinkingSpeed(float _speed)
  600. {
  601. m_BlinkingSpeed = _speed;
  602. }
  603. //! Returns the speed of blinks
  604. float GetBlinkingSpeed()
  605. {
  606. return m_BlinkingSpeed;
  607. }
  608. // handles blinking. Turns light on and off on regular intervals
  609. private void HandleBlinking(float time)
  610. {
  611. if ( m_BlinkingSpeed <= 0 )
  612. return;
  613. float multiplier;
  614. multiplier = Math.Sin(time * 0.001 * m_BlinkingSpeed); // Oscillate the multiplier overtime (time normalized to sec)
  615. multiplier = (multiplier + 1)/2; // Normalized the value to 0-1
  616. multiplier = Math.Round(multiplier); // Rounding to 0 or 1 to make it blink instantly
  617. SetBrightness(m_Brightness * multiplier);
  618. }
  619. };