Merge LL V3.7.10
commit
1f465086c0
1
.hgtags
1
.hgtags
|
|
@ -520,3 +520,4 @@ d029faf69f20a23007f32420a1ac6a3b89a6d441 3.7.6-release
|
|||
83959480cb986522d07b151a0c778ab7f920d41b 3.7.7-release
|
||||
bba9b3722eea08949e4ff69591f736bf0f808434 3.7.8-release
|
||||
a9f2d0cb11f73b06858e6083bb50083becc3f9cd 3.7.9-release
|
||||
91dae9494b4d147541c7a01902334ba19a7ec05e 3.7.10-release
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ project (llimage_libtest)
|
|||
include(00-Common)
|
||||
include(LLCommon)
|
||||
include(LLImage)
|
||||
include(LLMath)
|
||||
include(LLImageJ2COJ)
|
||||
include(LLKDU)
|
||||
include(LLVFS)
|
||||
|
|
@ -15,6 +16,7 @@ include_directories(
|
|||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
)
|
||||
include_directories(SYSTEM
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
|
|
@ -64,6 +66,7 @@ endif (DARWIN)
|
|||
target_link_libraries(llimage_libtest
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLIMAGE_LIBRARIES}
|
||||
${LLKDU_LIBRARIES}
|
||||
${KDU_LIBRARY}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.8</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blend</string>
|
||||
<real>10.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.1</real>
|
||||
<real>0.1</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>posterize</string>
|
||||
<real>10.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>gradient</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.15</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>uniform</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>gamma</string>
|
||||
<real>0.25</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>brighten</string>
|
||||
<real>0.5</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>10.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>colortransform</string>
|
||||
<real>0.2125</real>
|
||||
<real>0.7154</real>
|
||||
<real>0.0721</real>
|
||||
<real>0.2125</real>
|
||||
<real>0.7154</real>
|
||||
<real>0.0721</real>
|
||||
<real>0.2125</real>
|
||||
<real>0.7154</real>
|
||||
<real>0.0721</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.5</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>convolve</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>4.0</real>
|
||||
<real>1.0</real>
|
||||
<real>4.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>4.0</real>
|
||||
<real>1.0</real>
|
||||
<real>4.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>darken</string>
|
||||
<real>0.5</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.4</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>-0.8</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>gradient</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>2.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>0.4</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>sharpen</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>gamma</string>
|
||||
<real>1.7</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.8</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>fade</string>
|
||||
<real>0.5</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>4.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.4</real>
|
||||
<real>0.0</real>
|
||||
<real>0.2</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.015</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.02</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>add</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.1</real>
|
||||
<real>0.1</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.5</real>
|
||||
<real>5.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.6</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>5.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.6</real>
|
||||
<real>0.6</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>-0.5</real>
|
||||
<real>0.10</real>
|
||||
<real>20.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.7</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.6</real>
|
||||
<real>-0.6</real>
|
||||
<real>0.05</real>
|
||||
<real>20.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.7</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.4</real>
|
||||
<real>-0.4</real>
|
||||
<real>0.025</real>
|
||||
<real>20.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.7</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>brighten</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>add</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.1</real>
|
||||
<real>0.1</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.5</real>
|
||||
<real>5.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.8</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>5.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.8</real>
|
||||
<real>0.8</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.02</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.02</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>1.2</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>0.25</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.25</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>sharpen</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-0.25</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.25</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>2Dsine</string>
|
||||
<real>0.015</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.3</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>0.35</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>darken</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.9</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>posterize</string>
|
||||
<real>4.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>posterize</string>
|
||||
<real>10.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>rotate</string>
|
||||
<real>180.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>3.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>sepia</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>sharpen</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.015</real>
|
||||
<real>45.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.8</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>1.5</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>fade</string>
|
||||
<real>1.0</real>
|
||||
<real>0.25</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>0.8</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>brighten</string>
|
||||
<real>30</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>scanlines</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.1</real>
|
||||
<real>45.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>uniform</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>10.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>posterize</string>
|
||||
<real>50.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>gradient</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.025</real>
|
||||
<real>90.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.1</real>
|
||||
<real>0.2</real>
|
||||
<real>0.2</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>fade</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.2</real>
|
||||
<real>3.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.05</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.015</real>
|
||||
<real>90.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>darken</string>
|
||||
<real>0.15</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>uniform</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.02</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>gamma</string>
|
||||
<real>0.25</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
// Linden library includes
|
||||
#include "llimage.h"
|
||||
#include "llimagefilter.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llimagebmp.h"
|
||||
|
|
@ -39,6 +40,8 @@
|
|||
#include "llimagej2c.h"
|
||||
#include "lldir.h"
|
||||
#include "lldiriterator.h"
|
||||
#include "v4coloru.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
// system libraries
|
||||
#include <iostream>
|
||||
|
|
@ -83,6 +86,8 @@ static const char USAGE[] = "\n"
|
|||
" -rev, --reversible\n"
|
||||
" Set the compression to be lossless (reversible in j2c parlance).\n"
|
||||
" Only valid for output j2c images.\n"
|
||||
" -f, --filter <file>\n"
|
||||
" Apply the filter <file> to the input images.\n"
|
||||
" -log, --logmetrics <metric>\n"
|
||||
" Log performance data for <metric>. Results in <metric>.slp\n"
|
||||
" Note: so far, only ImageCompressionTester has been tested.\n"
|
||||
|
|
@ -99,7 +104,7 @@ static bool sAllDone = false;
|
|||
// Create an empty formatted image instance of the correct type from the filename
|
||||
LLPointer<LLImageFormatted> create_image(const std::string &filename)
|
||||
{
|
||||
std::string exten = gDirUtilp->getExtension(filename);
|
||||
std::string exten = gDirUtilp->getExtension(filename);
|
||||
LLPointer<LLImageFormatted> image = LLImageFormatted::createFromExtension(exten);
|
||||
return image;
|
||||
}
|
||||
|
|
@ -350,6 +355,7 @@ int main(int argc, char** argv)
|
|||
int blocks_size = -1;
|
||||
int levels = 0;
|
||||
bool reversible = false;
|
||||
std::string filter_name = "";
|
||||
|
||||
// Init whatever is necessary
|
||||
ll_init_apr();
|
||||
|
|
@ -523,7 +529,26 @@ int main(int argc, char** argv)
|
|||
break;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
|
||||
else if (!strcmp(argv[arg], "--filter") || !strcmp(argv[arg], "-f"))
|
||||
{
|
||||
// '--filter' needs to be specified with a named filter argument
|
||||
if ((arg + 1) < argc)
|
||||
{
|
||||
filter_name = argv[arg+1];
|
||||
}
|
||||
if (((arg + 1) >= argc) || (filter_name[0] == '-'))
|
||||
{
|
||||
// We don't have an argument left in the arg list or the next argument is another option
|
||||
std::cout << "No --filter argument given, no filter will be applied" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg += 1; // Skip that arg now we know it's a valid test name
|
||||
if ((arg + 1) == argc) // Break out of the loop if we reach the end of the arg list
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[arg], "--analyzeperformance") || !strcmp(argv[arg], "-a"))
|
||||
{
|
||||
analyze_performance = true;
|
||||
}
|
||||
|
|
@ -553,7 +578,10 @@ int main(int argc, char** argv)
|
|||
fast_timer_log_thread = new LogThread(LLFastTimer::sLogName);
|
||||
fast_timer_log_thread->start();
|
||||
}
|
||||
|
||||
|
||||
// Load the filter once and for all
|
||||
LLImageFilter filter(filter_name);
|
||||
|
||||
// Perform action on each input file
|
||||
std::list<std::string>::iterator in_file = input_filenames.begin();
|
||||
std::list<std::string>::iterator out_file = output_filenames.begin();
|
||||
|
|
@ -568,7 +596,10 @@ int main(int argc, char** argv)
|
|||
std::cout << "Error: Image " << *in_file << " could not be loaded" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Apply the filter
|
||||
filter.executeFilter(raw_image);
|
||||
|
||||
// Save file
|
||||
if (out_file != out_end)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ set(llimage_SOURCE_FILES
|
|||
llimage.cpp
|
||||
llimagedimensionsinfo.cpp
|
||||
llimagedxt.cpp
|
||||
llimagefilter.cpp
|
||||
llimagej2c.cpp
|
||||
llimagejpeg.cpp
|
||||
llimagepng.cpp
|
||||
|
|
@ -42,6 +43,7 @@ set(llimage_HEADER_FILES
|
|||
llimagebmp.h
|
||||
llimagedimensionsinfo.h
|
||||
llimagedxt.h
|
||||
llimagefilter.h
|
||||
llimagej2c.h
|
||||
llimagejpeg.h
|
||||
llimagepng.h
|
||||
|
|
|
|||
|
|
@ -471,18 +471,8 @@ void LLImageRaw::verticalFlip()
|
|||
void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
||||
{
|
||||
// Find new sizes
|
||||
S32 new_width = MIN_IMAGE_SIZE;
|
||||
S32 new_height = MIN_IMAGE_SIZE;
|
||||
|
||||
while( (new_width < getWidth()) && (new_width < max_dim) )
|
||||
{
|
||||
new_width <<= 1;
|
||||
}
|
||||
|
||||
while( (new_height < getHeight()) && (new_height < max_dim) )
|
||||
{
|
||||
new_height <<= 1;
|
||||
}
|
||||
S32 new_width = expandDimToPowerOfTwo(getWidth(), max_dim);
|
||||
S32 new_height = expandDimToPowerOfTwo(getHeight(), max_dim);
|
||||
|
||||
scale( new_width, new_height, scale_image );
|
||||
}
|
||||
|
|
@ -490,55 +480,61 @@ void LLImageRaw::expandToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
|||
void LLImageRaw::contractToPowerOfTwo(S32 max_dim, BOOL scale_image)
|
||||
{
|
||||
// Find new sizes
|
||||
S32 new_width = max_dim;
|
||||
S32 new_height = max_dim;
|
||||
|
||||
while( (new_width > getWidth()) && (new_width > MIN_IMAGE_SIZE) )
|
||||
{
|
||||
new_width >>= 1;
|
||||
}
|
||||
|
||||
while( (new_height > getHeight()) && (new_height > MIN_IMAGE_SIZE) )
|
||||
{
|
||||
new_height >>= 1;
|
||||
}
|
||||
S32 new_width = contractDimToPowerOfTwo(getWidth(), MIN_IMAGE_SIZE);
|
||||
S32 new_height = contractDimToPowerOfTwo(getHeight(), MIN_IMAGE_SIZE);
|
||||
|
||||
scale( new_width, new_height, scale_image );
|
||||
}
|
||||
|
||||
void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
|
||||
// static
|
||||
S32 LLImageRaw::biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
|
||||
{
|
||||
// Strong bias towards rounding down (to save bandwidth)
|
||||
// No bias would mean THRESHOLD == 1.5f;
|
||||
const F32 THRESHOLD = 1.75f;
|
||||
|
||||
const F32 THRESHOLD = 1.75f;
|
||||
|
||||
// Find new sizes
|
||||
S32 larger_w = max_dim; // 2^n >= mWidth
|
||||
S32 smaller_w = max_dim; // 2^(n-1) <= mWidth
|
||||
while( (smaller_w > getWidth()) && (smaller_w > MIN_IMAGE_SIZE) )
|
||||
S32 larger_dim = max_dim; // 2^n >= curr_dim
|
||||
S32 smaller_dim = max_dim; // 2^(n-1) <= curr_dim
|
||||
while( (smaller_dim > curr_dim) && (smaller_dim > MIN_IMAGE_SIZE) )
|
||||
{
|
||||
larger_w = smaller_w;
|
||||
smaller_w >>= 1;
|
||||
larger_dim = smaller_dim;
|
||||
smaller_dim >>= 1;
|
||||
}
|
||||
S32 new_width = ( (F32)getWidth() / smaller_w > THRESHOLD ) ? larger_w : smaller_w;
|
||||
return ( ((F32)curr_dim / (F32)smaller_dim) > THRESHOLD ) ? larger_dim : smaller_dim;
|
||||
}
|
||||
|
||||
|
||||
S32 larger_h = max_dim; // 2^m >= mHeight
|
||||
S32 smaller_h = max_dim; // 2^(m-1) <= mHeight
|
||||
while( (smaller_h > getHeight()) && (smaller_h > MIN_IMAGE_SIZE) )
|
||||
// static
|
||||
S32 LLImageRaw::expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim)
|
||||
{
|
||||
S32 new_dim = MIN_IMAGE_SIZE;
|
||||
while( (new_dim < curr_dim) && (new_dim < max_dim) )
|
||||
{
|
||||
larger_h = smaller_h;
|
||||
smaller_h >>= 1;
|
||||
new_dim <<= 1;
|
||||
}
|
||||
S32 new_height = ( (F32)getHeight() / smaller_h > THRESHOLD ) ? larger_h : smaller_h;
|
||||
return new_dim;
|
||||
}
|
||||
|
||||
// static
|
||||
S32 LLImageRaw::contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim)
|
||||
{
|
||||
S32 new_dim = MAX_IMAGE_SIZE;
|
||||
while( (new_dim > curr_dim) && (new_dim > min_dim) )
|
||||
{
|
||||
new_dim >>= 1;
|
||||
}
|
||||
return new_dim;
|
||||
}
|
||||
|
||||
void LLImageRaw::biasedScaleToPowerOfTwo(S32 max_dim)
|
||||
{
|
||||
// Find new sizes
|
||||
S32 new_width = biasedDimToPowerOfTwo(getWidth(),max_dim);
|
||||
S32 new_height = biasedDimToPowerOfTwo(getHeight(),max_dim);
|
||||
|
||||
scale( new_width, new_height );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Calculates (U8)(255*(a/255.f)*(b/255.f) + 0.5f). Thanks, Jim Blinn!
|
||||
inline U8 LLImageRaw::fastFractionalMult( U8 a, U8 b )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -216,6 +216,9 @@ public:
|
|||
|
||||
void verticalFlip();
|
||||
|
||||
static S32 biasedDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
|
||||
static S32 expandDimToPowerOfTwo(S32 curr_dim, S32 max_dim = MAX_IMAGE_SIZE);
|
||||
static S32 contractDimToPowerOfTwo(S32 curr_dim, S32 min_dim = MIN_IMAGE_SIZE);
|
||||
void expandToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
|
||||
void contractToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE, BOOL scale_image = TRUE);
|
||||
void biasedScaleToPowerOfTwo(S32 max_dim = MAX_IMAGE_SIZE);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,939 @@
|
|||
/**
|
||||
* @file llimagefilter.cpp
|
||||
* @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llimagefilter.h"
|
||||
|
||||
#include "llmath.h"
|
||||
#include "v3color.h"
|
||||
#include "v4coloru.h"
|
||||
#include "m3math.h"
|
||||
#include "v3math.h"
|
||||
#include "llsdserialize.h"
|
||||
#include "llstring.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLImageFilter
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLImageFilter::LLImageFilter(const std::string& file_path) :
|
||||
mFilterData(LLSD::emptyArray()),
|
||||
mImage(NULL),
|
||||
mHistoRed(NULL),
|
||||
mHistoGreen(NULL),
|
||||
mHistoBlue(NULL),
|
||||
mHistoBrightness(NULL),
|
||||
mStencilBlendMode(STENCIL_BLEND_MODE_BLEND),
|
||||
mStencilShape(STENCIL_SHAPE_UNIFORM),
|
||||
mStencilGamma(1.0),
|
||||
mStencilMin(0.0),
|
||||
mStencilMax(1.0)
|
||||
{
|
||||
// Load filter description from file
|
||||
llifstream filter_xml(file_path);
|
||||
if (filter_xml.is_open())
|
||||
{
|
||||
// Load and parse the file
|
||||
LLPointer<LLSDParser> parser = new LLSDXMLParser();
|
||||
parser->parse(filter_xml, mFilterData, LLSDSerialize::SIZE_UNLIMITED);
|
||||
filter_xml.close();
|
||||
}
|
||||
}
|
||||
|
||||
LLImageFilter::~LLImageFilter()
|
||||
{
|
||||
mImage = NULL;
|
||||
ll_aligned_free_16(mHistoRed);
|
||||
ll_aligned_free_16(mHistoGreen);
|
||||
ll_aligned_free_16(mHistoBlue);
|
||||
ll_aligned_free_16(mHistoBrightness);
|
||||
}
|
||||
|
||||
/*
|
||||
*TODO
|
||||
* Rename stencil to mask
|
||||
* Improve perf: use LUT for alpha blending in uniform case
|
||||
* Add gradient coloring as a filter
|
||||
*/
|
||||
|
||||
//============================================================================
|
||||
// Apply the filter data to the image passed as parameter
|
||||
//============================================================================
|
||||
|
||||
void LLImageFilter::executeFilter(LLPointer<LLImageRaw> raw_image)
|
||||
{
|
||||
mImage = raw_image;
|
||||
|
||||
//std::cout << "Filter : size = " << mFilterData.size() << std::endl;
|
||||
for (S32 i = 0; i < mFilterData.size(); ++i)
|
||||
{
|
||||
std::string filter_name = mFilterData[i][0].asString();
|
||||
// Dump out the filter values (for debug)
|
||||
//std::cout << "Filter : name = " << mFilterData[i][0].asString() << ", params = ";
|
||||
//for (S32 j = 1; j < mFilterData[i].size(); ++j)
|
||||
//{
|
||||
// std::cout << mFilterData[i][j].asString() << ", ";
|
||||
//}
|
||||
//std::cout << std::endl;
|
||||
|
||||
if (filter_name == "stencil")
|
||||
{
|
||||
// Get the shape of the stencil, that is how the procedural alpha is computed geometrically
|
||||
std::string filter_shape = mFilterData[i][1].asString();
|
||||
EStencilShape shape = STENCIL_SHAPE_UNIFORM;
|
||||
if (filter_shape == "uniform")
|
||||
{
|
||||
shape = STENCIL_SHAPE_UNIFORM;
|
||||
}
|
||||
else if (filter_shape == "gradient")
|
||||
{
|
||||
shape = STENCIL_SHAPE_GRADIENT;
|
||||
}
|
||||
else if (filter_shape == "vignette")
|
||||
{
|
||||
shape = STENCIL_SHAPE_VIGNETTE;
|
||||
}
|
||||
else if (filter_shape == "scanlines")
|
||||
{
|
||||
shape = STENCIL_SHAPE_SCAN_LINES;
|
||||
}
|
||||
// Get the blend mode of the stencil, that is how the effect is blended in the background through the stencil
|
||||
std::string filter_mode = mFilterData[i][2].asString();
|
||||
EStencilBlendMode mode = STENCIL_BLEND_MODE_BLEND;
|
||||
if (filter_mode == "blend")
|
||||
{
|
||||
mode = STENCIL_BLEND_MODE_BLEND;
|
||||
}
|
||||
else if (filter_mode == "add")
|
||||
{
|
||||
mode = STENCIL_BLEND_MODE_ADD;
|
||||
}
|
||||
else if (filter_mode == "add_back")
|
||||
{
|
||||
mode = STENCIL_BLEND_MODE_ABACK;
|
||||
}
|
||||
else if (filter_mode == "fade")
|
||||
{
|
||||
mode = STENCIL_BLEND_MODE_FADE;
|
||||
}
|
||||
// Get the float params: mandatory min, max then the optional parameters (4 max)
|
||||
F32 min = (F32)(mFilterData[i][3].asReal());
|
||||
F32 max = (F32)(mFilterData[i][4].asReal());
|
||||
F32 params[4] = {0.0, 0.0, 0.0, 0.0};
|
||||
for (S32 j = 5; (j < mFilterData[i].size()) && (j < 9); j++)
|
||||
{
|
||||
params[j-5] = (F32)(mFilterData[i][j].asReal());
|
||||
}
|
||||
// Set the stencil
|
||||
setStencil(shape,mode,min,max,params);
|
||||
}
|
||||
else if (filter_name == "sepia")
|
||||
{
|
||||
filterSepia();
|
||||
}
|
||||
else if (filter_name == "grayscale")
|
||||
{
|
||||
filterGrayScale();
|
||||
}
|
||||
else if (filter_name == "saturate")
|
||||
{
|
||||
filterSaturate((float)(mFilterData[i][1].asReal()));
|
||||
}
|
||||
else if (filter_name == "rotate")
|
||||
{
|
||||
filterRotate((float)(mFilterData[i][1].asReal()));
|
||||
}
|
||||
else if (filter_name == "gamma")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
|
||||
filterGamma((float)(mFilterData[i][1].asReal()),color);
|
||||
}
|
||||
else if (filter_name == "colorize")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][1].asReal()),(float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()));
|
||||
LLColor3 alpha((F32)(mFilterData[i][4].asReal()),(float)(mFilterData[i][5].asReal()),(float)(mFilterData[i][6].asReal()));
|
||||
filterColorize(color,alpha);
|
||||
}
|
||||
else if (filter_name == "contrast")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
|
||||
filterContrast((float)(mFilterData[i][1].asReal()),color);
|
||||
}
|
||||
else if (filter_name == "brighten")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
|
||||
filterBrightness((float)(mFilterData[i][1].asReal()),color);
|
||||
}
|
||||
else if (filter_name == "darken")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
|
||||
filterBrightness((float)(-mFilterData[i][1].asReal()),color);
|
||||
}
|
||||
else if (filter_name == "linearize")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
|
||||
filterLinearize((float)(mFilterData[i][1].asReal()),color);
|
||||
}
|
||||
else if (filter_name == "posterize")
|
||||
{
|
||||
LLColor3 color((float)(mFilterData[i][2].asReal()),(float)(mFilterData[i][3].asReal()),(float)(mFilterData[i][4].asReal()));
|
||||
filterEqualize((S32)(mFilterData[i][1].asReal()),color);
|
||||
}
|
||||
else if (filter_name == "screen")
|
||||
{
|
||||
std::string screen_name = mFilterData[i][1].asString();
|
||||
EScreenMode mode = SCREEN_MODE_2DSINE;
|
||||
if (screen_name == "2Dsine")
|
||||
{
|
||||
mode = SCREEN_MODE_2DSINE;
|
||||
}
|
||||
else if (screen_name == "line")
|
||||
{
|
||||
mode = SCREEN_MODE_LINE;
|
||||
}
|
||||
filterScreen(mode,(F32)(mFilterData[i][2].asReal()),(F32)(mFilterData[i][3].asReal()));
|
||||
}
|
||||
else if (filter_name == "blur")
|
||||
{
|
||||
LLMatrix3 kernel;
|
||||
for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
|
||||
for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
|
||||
kernel.mMatrix[i][j] = 1.0;
|
||||
convolve(kernel,true,false);
|
||||
}
|
||||
else if (filter_name == "sharpen")
|
||||
{
|
||||
LLMatrix3 kernel;
|
||||
for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
|
||||
for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
|
||||
kernel.mMatrix[k][j] = -1.0;
|
||||
kernel.mMatrix[1][1] = 9.0;
|
||||
convolve(kernel,false,false);
|
||||
}
|
||||
else if (filter_name == "gradient")
|
||||
{
|
||||
LLMatrix3 kernel;
|
||||
for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
|
||||
for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
|
||||
kernel.mMatrix[k][j] = -1.0;
|
||||
kernel.mMatrix[1][1] = 8.0;
|
||||
convolve(kernel,false,true);
|
||||
}
|
||||
else if (filter_name == "convolve")
|
||||
{
|
||||
LLMatrix3 kernel;
|
||||
S32 index = 1;
|
||||
bool normalize = (mFilterData[i][index++].asReal() > 0.0);
|
||||
bool abs_value = (mFilterData[i][index++].asReal() > 0.0);
|
||||
for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
|
||||
for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
|
||||
kernel.mMatrix[k][j] = mFilterData[i][index++].asReal();
|
||||
convolve(kernel,normalize,abs_value);
|
||||
}
|
||||
else if (filter_name == "colortransform")
|
||||
{
|
||||
LLMatrix3 transform;
|
||||
S32 index = 1;
|
||||
for (S32 k = 0; k < NUM_VALUES_IN_MAT3; k++)
|
||||
for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
|
||||
transform.mMatrix[k][j] = mFilterData[i][index++].asReal();
|
||||
transform.transpose();
|
||||
colorTransform(transform);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Filter unknown, cannot execute filter command : " << filter_name << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Filter Primitives
|
||||
//============================================================================
|
||||
|
||||
void LLImageFilter::blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue)
|
||||
{
|
||||
F32 inv_alpha = 1.0 - alpha;
|
||||
switch (mStencilBlendMode)
|
||||
{
|
||||
case STENCIL_BLEND_MODE_BLEND:
|
||||
// Classic blend of incoming color with the background image
|
||||
pixel[VRED] = inv_alpha * pixel[VRED] + alpha * red;
|
||||
pixel[VGREEN] = inv_alpha * pixel[VGREEN] + alpha * green;
|
||||
pixel[VBLUE] = inv_alpha * pixel[VBLUE] + alpha * blue;
|
||||
break;
|
||||
case STENCIL_BLEND_MODE_ADD:
|
||||
// Add incoming color to the background image
|
||||
pixel[VRED] = llclampb(pixel[VRED] + alpha * red);
|
||||
pixel[VGREEN] = llclampb(pixel[VGREEN] + alpha * green);
|
||||
pixel[VBLUE] = llclampb(pixel[VBLUE] + alpha * blue);
|
||||
break;
|
||||
case STENCIL_BLEND_MODE_ABACK:
|
||||
// Add back background image to the incoming color
|
||||
pixel[VRED] = llclampb(inv_alpha * pixel[VRED] + red);
|
||||
pixel[VGREEN] = llclampb(inv_alpha * pixel[VGREEN] + green);
|
||||
pixel[VBLUE] = llclampb(inv_alpha * pixel[VBLUE] + blue);
|
||||
break;
|
||||
case STENCIL_BLEND_MODE_FADE:
|
||||
// Fade incoming color to black
|
||||
pixel[VRED] = alpha * red;
|
||||
pixel[VGREEN] = alpha * green;
|
||||
pixel[VBLUE] = alpha * blue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageFilter::colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue)
|
||||
{
|
||||
const S32 components = mImage->getComponents();
|
||||
llassert( components >= 1 && components <= 4 );
|
||||
|
||||
S32 width = mImage->getWidth();
|
||||
S32 height = mImage->getHeight();
|
||||
|
||||
U8* dst_data = mImage->getData();
|
||||
for (S32 j = 0; j < height; j++)
|
||||
{
|
||||
for (S32 i = 0; i < width; i++)
|
||||
{
|
||||
// Blend LUT value
|
||||
blendStencil(getStencilAlpha(i,j), dst_data, lut_red[dst_data[VRED]], lut_green[dst_data[VGREEN]], lut_blue[dst_data[VBLUE]]);
|
||||
dst_data += components;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageFilter::colorTransform(const LLMatrix3 &transform)
|
||||
{
|
||||
const S32 components = mImage->getComponents();
|
||||
llassert( components >= 1 && components <= 4 );
|
||||
|
||||
S32 width = mImage->getWidth();
|
||||
S32 height = mImage->getHeight();
|
||||
|
||||
U8* dst_data = mImage->getData();
|
||||
for (S32 j = 0; j < height; j++)
|
||||
{
|
||||
for (S32 i = 0; i < width; i++)
|
||||
{
|
||||
// Compute transform
|
||||
LLVector3 src((F32)(dst_data[VRED]),(F32)(dst_data[VGREEN]),(F32)(dst_data[VBLUE]));
|
||||
LLVector3 dst = src * transform;
|
||||
dst.clamp(0.0f,255.0f);
|
||||
|
||||
// Blend result
|
||||
blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
|
||||
dst_data += components;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageFilter::convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value)
|
||||
{
|
||||
const S32 components = mImage->getComponents();
|
||||
llassert( components >= 1 && components <= 4 );
|
||||
|
||||
// Compute normalization factors
|
||||
F32 kernel_min = 0.0;
|
||||
F32 kernel_max = 0.0;
|
||||
for (S32 i = 0; i < NUM_VALUES_IN_MAT3; i++)
|
||||
{
|
||||
for (S32 j = 0; j < NUM_VALUES_IN_MAT3; j++)
|
||||
{
|
||||
if (kernel.mMatrix[i][j] >= 0.0)
|
||||
kernel_max += kernel.mMatrix[i][j];
|
||||
else
|
||||
kernel_min += kernel.mMatrix[i][j];
|
||||
}
|
||||
}
|
||||
if (abs_value)
|
||||
{
|
||||
kernel_max = llabs(kernel_max);
|
||||
kernel_min = llabs(kernel_min);
|
||||
kernel_max = llmax(kernel_max,kernel_min);
|
||||
kernel_min = 0.0;
|
||||
}
|
||||
F32 kernel_range = kernel_max - kernel_min;
|
||||
|
||||
// Allocate temporary buffers and initialize algorithm's data
|
||||
S32 width = mImage->getWidth();
|
||||
S32 height = mImage->getHeight();
|
||||
|
||||
U8* dst_data = mImage->getData();
|
||||
|
||||
S32 buffer_size = width * components;
|
||||
llassert_always(buffer_size > 0);
|
||||
std::vector<U8> even_buffer(buffer_size);
|
||||
std::vector<U8> odd_buffer(buffer_size);
|
||||
|
||||
U8* south_data = dst_data + buffer_size;
|
||||
U8* east_west_data;
|
||||
U8* north_data;
|
||||
|
||||
// Line 0 : we set the line to 0 (debatable)
|
||||
memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
|
||||
for (S32 i = 0; i < width; i++)
|
||||
{
|
||||
blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
|
||||
dst_data += components;
|
||||
}
|
||||
south_data += buffer_size;
|
||||
|
||||
// All other lines
|
||||
for (S32 j = 1; j < (height-1); j++)
|
||||
{
|
||||
// We need to buffer 2 lines. We flip north and east-west (current) to avoid moving too much memory around
|
||||
if (j % 2)
|
||||
{
|
||||
memcpy( &odd_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
|
||||
east_west_data = &odd_buffer[0];
|
||||
north_data = &even_buffer[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy( &even_buffer[0], dst_data, buffer_size ); /* Flawfinder: ignore */
|
||||
east_west_data = &even_buffer[0];
|
||||
north_data = &odd_buffer[0];
|
||||
}
|
||||
// First pixel : set to 0
|
||||
blendStencil(getStencilAlpha(0,j), dst_data, 0, 0, 0);
|
||||
dst_data += components;
|
||||
// Set pointers to kernel
|
||||
U8* NW = north_data;
|
||||
U8* N = NW+components;
|
||||
U8* NE = N+components;
|
||||
U8* W = east_west_data;
|
||||
U8* C = W+components;
|
||||
U8* E = C+components;
|
||||
U8* SW = south_data;
|
||||
U8* S = SW+components;
|
||||
U8* SE = S+components;
|
||||
// All other pixels
|
||||
for (S32 i = 1; i < (width-1); i++)
|
||||
{
|
||||
// Compute convolution
|
||||
LLVector3 dst;
|
||||
dst.mV[VRED] = (kernel.mMatrix[0][0]*NW[VRED] + kernel.mMatrix[0][1]*N[VRED] + kernel.mMatrix[0][2]*NE[VRED] +
|
||||
kernel.mMatrix[1][0]*W[VRED] + kernel.mMatrix[1][1]*C[VRED] + kernel.mMatrix[1][2]*E[VRED] +
|
||||
kernel.mMatrix[2][0]*SW[VRED] + kernel.mMatrix[2][1]*S[VRED] + kernel.mMatrix[2][2]*SE[VRED]);
|
||||
dst.mV[VGREEN] = (kernel.mMatrix[0][0]*NW[VGREEN] + kernel.mMatrix[0][1]*N[VGREEN] + kernel.mMatrix[0][2]*NE[VGREEN] +
|
||||
kernel.mMatrix[1][0]*W[VGREEN] + kernel.mMatrix[1][1]*C[VGREEN] + kernel.mMatrix[1][2]*E[VGREEN] +
|
||||
kernel.mMatrix[2][0]*SW[VGREEN] + kernel.mMatrix[2][1]*S[VGREEN] + kernel.mMatrix[2][2]*SE[VGREEN]);
|
||||
dst.mV[VBLUE] = (kernel.mMatrix[0][0]*NW[VBLUE] + kernel.mMatrix[0][1]*N[VBLUE] + kernel.mMatrix[0][2]*NE[VBLUE] +
|
||||
kernel.mMatrix[1][0]*W[VBLUE] + kernel.mMatrix[1][1]*C[VBLUE] + kernel.mMatrix[1][2]*E[VBLUE] +
|
||||
kernel.mMatrix[2][0]*SW[VBLUE] + kernel.mMatrix[2][1]*S[VBLUE] + kernel.mMatrix[2][2]*SE[VBLUE]);
|
||||
if (abs_value)
|
||||
{
|
||||
dst.mV[VRED] = llabs(dst.mV[VRED]);
|
||||
dst.mV[VGREEN] = llabs(dst.mV[VGREEN]);
|
||||
dst.mV[VBLUE] = llabs(dst.mV[VBLUE]);
|
||||
}
|
||||
if (normalize)
|
||||
{
|
||||
dst.mV[VRED] = (dst.mV[VRED] - kernel_min)/kernel_range;
|
||||
dst.mV[VGREEN] = (dst.mV[VGREEN] - kernel_min)/kernel_range;
|
||||
dst.mV[VBLUE] = (dst.mV[VBLUE] - kernel_min)/kernel_range;
|
||||
}
|
||||
dst.clamp(0.0f,255.0f);
|
||||
|
||||
// Blend result
|
||||
blendStencil(getStencilAlpha(i,j), dst_data, dst.mV[VRED], dst.mV[VGREEN], dst.mV[VBLUE]);
|
||||
|
||||
// Next pixel
|
||||
dst_data += components;
|
||||
NW += components;
|
||||
N += components;
|
||||
NE += components;
|
||||
W += components;
|
||||
C += components;
|
||||
E += components;
|
||||
SW += components;
|
||||
S += components;
|
||||
SE += components;
|
||||
}
|
||||
// Last pixel : set to 0
|
||||
blendStencil(getStencilAlpha(width-1,j), dst_data, 0, 0, 0);
|
||||
dst_data += components;
|
||||
south_data += buffer_size;
|
||||
}
|
||||
|
||||
// Last line
|
||||
for (S32 i = 0; i < width; i++)
|
||||
{
|
||||
blendStencil(getStencilAlpha(i,0), dst_data, 0, 0, 0);
|
||||
dst_data += components;
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageFilter::filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle)
|
||||
{
|
||||
const S32 components = mImage->getComponents();
|
||||
llassert( components >= 1 && components <= 4 );
|
||||
|
||||
S32 width = mImage->getWidth();
|
||||
S32 height = mImage->getHeight();
|
||||
|
||||
F32 wave_length_pixels = wave_length * (F32)(height) / 2.0;
|
||||
F32 sin = sinf(angle*DEG_TO_RAD);
|
||||
F32 cos = cosf(angle*DEG_TO_RAD);
|
||||
|
||||
// Precompute the gamma table : gives us the gray level to use when cutting outside the screen (prevents strong aliasing on the screen)
|
||||
U8 gamma[256];
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/4.0)));
|
||||
gamma[i] = (U8)(255.0 * gamma_i);
|
||||
}
|
||||
|
||||
U8* dst_data = mImage->getData();
|
||||
for (S32 j = 0; j < height; j++)
|
||||
{
|
||||
for (S32 i = 0; i < width; i++)
|
||||
{
|
||||
// Compute screen value
|
||||
F32 value = 0.0;
|
||||
F32 di = 0.0;
|
||||
F32 dj = 0.0;
|
||||
switch (mode)
|
||||
{
|
||||
case SCREEN_MODE_2DSINE:
|
||||
di = cos*i + sin*j;
|
||||
dj = -sin*i + cos*j;
|
||||
value = (sinf(2*F_PI*di/wave_length_pixels)*sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
|
||||
break;
|
||||
case SCREEN_MODE_LINE:
|
||||
dj = sin*i - cos*j;
|
||||
value = (sinf(2*F_PI*dj/wave_length_pixels)+1.0)*255.0/2.0;
|
||||
break;
|
||||
}
|
||||
U8 dst_value = (dst_data[VRED] >= (U8)(value) ? gamma[dst_data[VRED] - (U8)(value)] : 0);
|
||||
|
||||
// Blend result
|
||||
blendStencil(getStencilAlpha(i,j), dst_data, dst_value, dst_value, dst_value);
|
||||
dst_data += components;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Procedural Stencils
|
||||
//============================================================================
|
||||
void LLImageFilter::setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params)
|
||||
{
|
||||
mStencilShape = shape;
|
||||
mStencilBlendMode = mode;
|
||||
mStencilMin = llmin(llmax(min, -1.0f), 1.0f);
|
||||
mStencilMax = llmin(llmax(max, -1.0f), 1.0f);
|
||||
|
||||
// Each shape will interpret the 4 params differenly.
|
||||
// We compute each systematically, though, clearly, values are meaningless when the shape doesn't correspond to the parameters
|
||||
mStencilCenterX = (S32)(mImage->getWidth() + params[0] * (F32)(mImage->getHeight()))/2;
|
||||
mStencilCenterY = (S32)(mImage->getHeight() + params[1] * (F32)(mImage->getHeight()))/2;
|
||||
mStencilWidth = (S32)(params[2] * (F32)(mImage->getHeight()))/2;
|
||||
mStencilGamma = (params[3] <= 0.0 ? 1.0 : params[3]);
|
||||
|
||||
mStencilWavelength = (params[0] <= 0.0 ? 10.0 : params[0] * (F32)(mImage->getHeight()) / 2.0);
|
||||
mStencilSine = sinf(params[1]*DEG_TO_RAD);
|
||||
mStencilCosine = cosf(params[1]*DEG_TO_RAD);
|
||||
|
||||
mStencilStartX = ((F32)(mImage->getWidth()) + params[0] * (F32)(mImage->getHeight()))/2.0;
|
||||
mStencilStartY = ((F32)(mImage->getHeight()) + params[1] * (F32)(mImage->getHeight()))/2.0;
|
||||
F32 end_x = ((F32)(mImage->getWidth()) + params[2] * (F32)(mImage->getHeight()))/2.0;
|
||||
F32 end_y = ((F32)(mImage->getHeight()) + params[3] * (F32)(mImage->getHeight()))/2.0;
|
||||
mStencilGradX = end_x - mStencilStartX;
|
||||
mStencilGradY = end_y - mStencilStartY;
|
||||
mStencilGradN = mStencilGradX*mStencilGradX + mStencilGradY*mStencilGradY;
|
||||
}
|
||||
|
||||
F32 LLImageFilter::getStencilAlpha(S32 i, S32 j)
|
||||
{
|
||||
F32 alpha = 1.0; // That init actually takes care of the STENCIL_SHAPE_UNIFORM case...
|
||||
if (mStencilShape == STENCIL_SHAPE_VIGNETTE)
|
||||
{
|
||||
// alpha is a modified gaussian value, with a center and fading in a circular pattern toward the edges
|
||||
// The gamma parameter controls the intensity of the drop down from alpha 1.0 (center) to 0.0
|
||||
F32 d_center_square = (i - mStencilCenterX)*(i - mStencilCenterX) + (j - mStencilCenterY)*(j - mStencilCenterY);
|
||||
alpha = powf(F_E, -(powf((d_center_square/(mStencilWidth*mStencilWidth)),mStencilGamma)/2.0f));
|
||||
}
|
||||
else if (mStencilShape == STENCIL_SHAPE_SCAN_LINES)
|
||||
{
|
||||
// alpha varies according to a squared sine function.
|
||||
F32 d = mStencilSine*i - mStencilCosine*j;
|
||||
alpha = (sinf(2*F_PI*d/mStencilWavelength) > 0.0 ? 1.0 : 0.0);
|
||||
}
|
||||
else if (mStencilShape == STENCIL_SHAPE_GRADIENT)
|
||||
{
|
||||
alpha = (((F32)(i) - mStencilStartX)*mStencilGradX + ((F32)(j) - mStencilStartY)*mStencilGradY) / mStencilGradN;
|
||||
alpha = llclampf(alpha);
|
||||
}
|
||||
|
||||
// We rescale alpha between min and max
|
||||
return (mStencilMin + alpha * (mStencilMax - mStencilMin));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Histograms
|
||||
//============================================================================
|
||||
|
||||
U32* LLImageFilter::getBrightnessHistogram()
|
||||
{
|
||||
if (!mHistoBrightness)
|
||||
{
|
||||
computeHistograms();
|
||||
}
|
||||
return mHistoBrightness;
|
||||
}
|
||||
|
||||
void LLImageFilter::computeHistograms()
|
||||
{
|
||||
const S32 components = mImage->getComponents();
|
||||
llassert( components >= 1 && components <= 4 );
|
||||
|
||||
// Allocate memory for the histograms
|
||||
if (!mHistoRed)
|
||||
{
|
||||
mHistoRed = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
|
||||
}
|
||||
if (!mHistoGreen)
|
||||
{
|
||||
mHistoGreen = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
|
||||
}
|
||||
if (!mHistoBlue)
|
||||
{
|
||||
mHistoBlue = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
|
||||
}
|
||||
if (!mHistoBrightness)
|
||||
{
|
||||
mHistoBrightness = (U32*) ll_aligned_malloc_16(256*sizeof(U32));
|
||||
}
|
||||
|
||||
// Initialize them
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
mHistoRed[i] = 0;
|
||||
mHistoGreen[i] = 0;
|
||||
mHistoBlue[i] = 0;
|
||||
mHistoBrightness[i] = 0;
|
||||
}
|
||||
|
||||
// Compute them
|
||||
S32 pixels = mImage->getWidth() * mImage->getHeight();
|
||||
U8* dst_data = mImage->getData();
|
||||
for (S32 i = 0; i < pixels; i++)
|
||||
{
|
||||
mHistoRed[dst_data[VRED]]++;
|
||||
mHistoGreen[dst_data[VGREEN]]++;
|
||||
mHistoBlue[dst_data[VBLUE]]++;
|
||||
// Note: this is a very simple shorthand for brightness but it's OK for our use
|
||||
S32 brightness = ((S32)(dst_data[VRED]) + (S32)(dst_data[VGREEN]) + (S32)(dst_data[VBLUE])) / 3;
|
||||
mHistoBrightness[brightness]++;
|
||||
// next pixel...
|
||||
dst_data += components;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
// Secondary Filters
|
||||
//============================================================================
|
||||
|
||||
void LLImageFilter::filterGrayScale()
|
||||
{
|
||||
LLMatrix3 gray_scale;
|
||||
LLVector3 luminosity(0.2125, 0.7154, 0.0721);
|
||||
gray_scale.setRows(luminosity, luminosity, luminosity);
|
||||
gray_scale.transpose();
|
||||
colorTransform(gray_scale);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterSepia()
|
||||
{
|
||||
LLMatrix3 sepia;
|
||||
sepia.setRows(LLVector3(0.3588, 0.7044, 0.1368),
|
||||
LLVector3(0.2990, 0.5870, 0.1140),
|
||||
LLVector3(0.2392, 0.4696, 0.0912));
|
||||
sepia.transpose();
|
||||
colorTransform(sepia);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterSaturate(F32 saturation)
|
||||
{
|
||||
// Matrix to Lij
|
||||
LLMatrix3 r_a;
|
||||
LLMatrix3 r_b;
|
||||
|
||||
// 45 degre rotation around z
|
||||
r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0),
|
||||
LLVector3(-OO_SQRT2, OO_SQRT2, 0.0),
|
||||
LLVector3( 0.0, 0.0, 1.0));
|
||||
// 54.73 degre rotation around y
|
||||
float oo_sqrt3 = 1.0f / F_SQRT3;
|
||||
float sin_54 = F_SQRT2 * oo_sqrt3;
|
||||
r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
|
||||
LLVector3(0.0, 1.0, 0.0),
|
||||
LLVector3(sin_54, 0.0, oo_sqrt3));
|
||||
|
||||
// Coordinate conversion
|
||||
LLMatrix3 Lij = r_b * r_a;
|
||||
LLMatrix3 Lij_inv = Lij;
|
||||
Lij_inv.transpose();
|
||||
|
||||
// Local saturation transform
|
||||
LLMatrix3 s;
|
||||
s.setRows(LLVector3(saturation, 0.0, 0.0),
|
||||
LLVector3(0.0, saturation, 0.0),
|
||||
LLVector3(0.0, 0.0, 1.0));
|
||||
|
||||
// Global saturation transform
|
||||
LLMatrix3 transfo = Lij_inv * s * Lij;
|
||||
colorTransform(transfo);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterRotate(F32 angle)
|
||||
{
|
||||
// Matrix to Lij
|
||||
LLMatrix3 r_a;
|
||||
LLMatrix3 r_b;
|
||||
|
||||
// 45 degre rotation around z
|
||||
r_a.setRows(LLVector3( OO_SQRT2, OO_SQRT2, 0.0),
|
||||
LLVector3(-OO_SQRT2, OO_SQRT2, 0.0),
|
||||
LLVector3( 0.0, 0.0, 1.0));
|
||||
// 54.73 degre rotation around y
|
||||
float oo_sqrt3 = 1.0f / F_SQRT3;
|
||||
float sin_54 = F_SQRT2 * oo_sqrt3;
|
||||
r_b.setRows(LLVector3(oo_sqrt3, 0.0, -sin_54),
|
||||
LLVector3(0.0, 1.0, 0.0),
|
||||
LLVector3(sin_54, 0.0, oo_sqrt3));
|
||||
|
||||
// Coordinate conversion
|
||||
LLMatrix3 Lij = r_b * r_a;
|
||||
LLMatrix3 Lij_inv = Lij;
|
||||
Lij_inv.transpose();
|
||||
|
||||
// Local color rotation transform
|
||||
LLMatrix3 r;
|
||||
angle *= DEG_TO_RAD;
|
||||
r.setRows(LLVector3( cosf(angle), sinf(angle), 0.0),
|
||||
LLVector3(-sinf(angle), cosf(angle), 0.0),
|
||||
LLVector3( 0.0, 0.0, 1.0));
|
||||
|
||||
// Global color rotation transform
|
||||
LLMatrix3 transfo = Lij_inv * r * Lij;
|
||||
colorTransform(transfo);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterGamma(F32 gamma, const LLColor3& alpha)
|
||||
{
|
||||
U8 gamma_red_lut[256];
|
||||
U8 gamma_green_lut[256];
|
||||
U8 gamma_blue_lut[256];
|
||||
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
F32 gamma_i = llclampf((float)(powf((float)(i)/255.0,1.0/gamma)));
|
||||
// Blend in with alpha values
|
||||
gamma_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * 255.0 * gamma_i);
|
||||
gamma_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * 255.0 * gamma_i);
|
||||
gamma_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * 255.0 * gamma_i);
|
||||
}
|
||||
|
||||
colorCorrect(gamma_red_lut,gamma_green_lut,gamma_blue_lut);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterLinearize(F32 tail, const LLColor3& alpha)
|
||||
{
|
||||
// Get the histogram
|
||||
U32* histo = getBrightnessHistogram();
|
||||
|
||||
// Compute cumulated histogram
|
||||
U32 cumulated_histo[256];
|
||||
cumulated_histo[0] = histo[0];
|
||||
for (S32 i = 1; i < 256; i++)
|
||||
{
|
||||
cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
|
||||
}
|
||||
|
||||
// Compute min and max counts minus tail
|
||||
tail = llclampf(tail);
|
||||
S32 total = cumulated_histo[255];
|
||||
S32 min_c = (S32)((F32)(total) * tail);
|
||||
S32 max_c = (S32)((F32)(total) * (1.0 - tail));
|
||||
|
||||
// Find min and max values
|
||||
S32 min_v = 0;
|
||||
while (cumulated_histo[min_v] < min_c)
|
||||
{
|
||||
min_v++;
|
||||
}
|
||||
S32 max_v = 255;
|
||||
while (cumulated_histo[max_v] > max_c)
|
||||
{
|
||||
max_v--;
|
||||
}
|
||||
|
||||
// Compute linear lookup table
|
||||
U8 linear_red_lut[256];
|
||||
U8 linear_green_lut[256];
|
||||
U8 linear_blue_lut[256];
|
||||
if (max_v == min_v)
|
||||
{
|
||||
// Degenerated binary split case
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
U8 value_i = (i < min_v ? 0 : 255);
|
||||
// Blend in with alpha values
|
||||
linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
|
||||
linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
|
||||
linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Linearize between min and max
|
||||
F32 slope = 255.0 / (F32)(max_v - min_v);
|
||||
F32 translate = -min_v * slope;
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
|
||||
// Blend in with alpha values
|
||||
linear_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
|
||||
linear_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
|
||||
linear_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply lookup table
|
||||
colorCorrect(linear_red_lut,linear_green_lut,linear_blue_lut);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterEqualize(S32 nb_classes, const LLColor3& alpha)
|
||||
{
|
||||
// Regularize the parameter: must be between 2 and 255
|
||||
nb_classes = llmax(nb_classes,2);
|
||||
nb_classes = llclampb(nb_classes);
|
||||
|
||||
// Get the histogram
|
||||
U32* histo = getBrightnessHistogram();
|
||||
|
||||
// Compute cumulated histogram
|
||||
U32 cumulated_histo[256];
|
||||
cumulated_histo[0] = histo[0];
|
||||
for (S32 i = 1; i < 256; i++)
|
||||
{
|
||||
cumulated_histo[i] = cumulated_histo[i-1] + histo[i];
|
||||
}
|
||||
|
||||
// Compute deltas
|
||||
S32 total = cumulated_histo[255];
|
||||
S32 delta_count = total / nb_classes;
|
||||
S32 current_count = delta_count;
|
||||
S32 delta_value = 256 / (nb_classes - 1);
|
||||
S32 current_value = 0;
|
||||
|
||||
// Compute equalized lookup table
|
||||
U8 equalize_red_lut[256];
|
||||
U8 equalize_green_lut[256];
|
||||
U8 equalize_blue_lut[256];
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
// Blend in current_value with alpha values
|
||||
equalize_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * current_value);
|
||||
equalize_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * current_value);
|
||||
equalize_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * current_value);
|
||||
if (cumulated_histo[i] >= current_count)
|
||||
{
|
||||
current_count += delta_count;
|
||||
current_value += delta_value;
|
||||
current_value = llclampb(current_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply lookup table
|
||||
colorCorrect(equalize_red_lut,equalize_green_lut,equalize_blue_lut);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterColorize(const LLColor3& color, const LLColor3& alpha)
|
||||
{
|
||||
U8 red_lut[256];
|
||||
U8 green_lut[256];
|
||||
U8 blue_lut[256];
|
||||
|
||||
F32 red_composite = 255.0 * alpha.mV[0] * color.mV[0];
|
||||
F32 green_composite = 255.0 * alpha.mV[1] * color.mV[1];
|
||||
F32 blue_composite = 255.0 * alpha.mV[2] * color.mV[2];
|
||||
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
red_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[0]) * (F32)(i) + red_composite)));
|
||||
green_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[1]) * (F32)(i) + green_composite)));
|
||||
blue_lut[i] = (U8)(llclampb((S32)((1.0 - alpha.mV[2]) * (F32)(i) + blue_composite)));
|
||||
}
|
||||
|
||||
colorCorrect(red_lut,green_lut,blue_lut);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterContrast(F32 slope, const LLColor3& alpha)
|
||||
{
|
||||
U8 contrast_red_lut[256];
|
||||
U8 contrast_green_lut[256];
|
||||
U8 contrast_blue_lut[256];
|
||||
|
||||
F32 translate = 128.0 * (1.0 - slope);
|
||||
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
U8 value_i = (U8)(llclampb((S32)(slope*i + translate)));
|
||||
// Blend in with alpha values
|
||||
contrast_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
|
||||
contrast_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
|
||||
contrast_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
|
||||
}
|
||||
|
||||
colorCorrect(contrast_red_lut,contrast_green_lut,contrast_blue_lut);
|
||||
}
|
||||
|
||||
void LLImageFilter::filterBrightness(F32 add, const LLColor3& alpha)
|
||||
{
|
||||
U8 brightness_red_lut[256];
|
||||
U8 brightness_green_lut[256];
|
||||
U8 brightness_blue_lut[256];
|
||||
|
||||
S32 add_value = (S32)(add * 255.0);
|
||||
|
||||
for (S32 i = 0; i < 256; i++)
|
||||
{
|
||||
U8 value_i = (U8)(llclampb(i + add_value));
|
||||
// Blend in with alpha values
|
||||
brightness_red_lut[i] = (U8)((1.0 - alpha.mV[0]) * (float)(i) + alpha.mV[0] * value_i);
|
||||
brightness_green_lut[i] = (U8)((1.0 - alpha.mV[1]) * (float)(i) + alpha.mV[1] * value_i);
|
||||
brightness_blue_lut[i] = (U8)((1.0 - alpha.mV[2]) * (float)(i) + alpha.mV[2] * value_i);
|
||||
}
|
||||
|
||||
colorCorrect(brightness_red_lut,brightness_green_lut,brightness_blue_lut);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* @file llimagefilter.h
|
||||
* @brief Simple Image Filtering. See https://wiki.lindenlab.com/wiki/SL_Viewer_Image_Filters for complete documentation.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLIMAGEFILTER_H
|
||||
#define LL_LLIMAGEFILTER_H
|
||||
|
||||
#include "llsd.h"
|
||||
#include "llimage.h"
|
||||
|
||||
class LLImageRaw;
|
||||
class LLColor4U;
|
||||
class LLColor3;
|
||||
class LLMatrix3;
|
||||
|
||||
typedef enum e_stencil_blend_mode
|
||||
{
|
||||
STENCIL_BLEND_MODE_BLEND = 0,
|
||||
STENCIL_BLEND_MODE_ADD = 1,
|
||||
STENCIL_BLEND_MODE_ABACK = 2,
|
||||
STENCIL_BLEND_MODE_FADE = 3
|
||||
} EStencilBlendMode;
|
||||
|
||||
typedef enum e_stencil_shape
|
||||
{
|
||||
STENCIL_SHAPE_UNIFORM = 0,
|
||||
STENCIL_SHAPE_GRADIENT = 1,
|
||||
STENCIL_SHAPE_VIGNETTE = 2,
|
||||
STENCIL_SHAPE_SCAN_LINES = 3
|
||||
} EStencilShape;
|
||||
|
||||
typedef enum e_screen_mode
|
||||
{
|
||||
SCREEN_MODE_2DSINE = 0,
|
||||
SCREEN_MODE_LINE = 1
|
||||
} EScreenMode;
|
||||
|
||||
//============================================================================
|
||||
// LLImageFilter
|
||||
//============================================================================
|
||||
|
||||
class LLImageFilter
|
||||
{
|
||||
public:
|
||||
LLImageFilter(const std::string& file_path);
|
||||
~LLImageFilter();
|
||||
|
||||
void executeFilter(LLPointer<LLImageRaw> raw_image);
|
||||
|
||||
private:
|
||||
// Filter Operations : Transforms
|
||||
void filterGrayScale(); // Convert to grayscale
|
||||
void filterSepia(); // Convert to sepia
|
||||
void filterSaturate(F32 saturation); // < 1.0 desaturates, > 1.0 saturates
|
||||
void filterRotate(F32 angle); // Rotates hue according to angle, angle in degrees
|
||||
|
||||
// Filter Operations : Color Corrections
|
||||
// When specified, the LLColor3 alpha parameter indicates the intensity of the effect for each color channel
|
||||
// acting in effect as an alpha blending factor different for each channel. For instance (1.0,0.0,0.0) will apply
|
||||
// the effect only to the Red channel. Intermediate values blends the effect with the source color.
|
||||
void filterGamma(F32 gamma, const LLColor3& alpha); // Apply gamma to each channel
|
||||
void filterLinearize(F32 tail, const LLColor3& alpha); // Use histogram to linearize constrast between min and max values minus tail
|
||||
void filterEqualize(S32 nb_classes, const LLColor3& alpha); // Use histogram to equalize constrast between nb_classes throughout the image
|
||||
void filterColorize(const LLColor3& color, const LLColor3& alpha); // Colorize with color and alpha per channel
|
||||
void filterContrast(F32 slope, const LLColor3& alpha); // Change contrast according to slope: > 1.0 more contrast, < 1.0 less contrast
|
||||
void filterBrightness(F32 add, const LLColor3& alpha); // Change brightness according to add: > 0 brighter, < 0 darker
|
||||
|
||||
// Filter Primitives
|
||||
void colorTransform(const LLMatrix3 &transform);
|
||||
void colorCorrect(const U8* lut_red, const U8* lut_green, const U8* lut_blue);
|
||||
void filterScreen(EScreenMode mode, const F32 wave_length, const F32 angle);
|
||||
void blendStencil(F32 alpha, U8* pixel, U8 red, U8 green, U8 blue);
|
||||
void convolve(const LLMatrix3 &kernel, bool normalize, bool abs_value);
|
||||
|
||||
// Procedural Stencils
|
||||
void setStencil(EStencilShape shape, EStencilBlendMode mode, F32 min, F32 max, F32* params);
|
||||
F32 getStencilAlpha(S32 i, S32 j);
|
||||
|
||||
// Histograms
|
||||
U32* getBrightnessHistogram();
|
||||
void computeHistograms();
|
||||
|
||||
LLSD mFilterData;
|
||||
LLPointer<LLImageRaw> mImage;
|
||||
|
||||
// Histograms (if we ever happen to need them)
|
||||
U32 *mHistoRed;
|
||||
U32 *mHistoGreen;
|
||||
U32 *mHistoBlue;
|
||||
U32 *mHistoBrightness;
|
||||
|
||||
// Current Stencil Settings
|
||||
EStencilBlendMode mStencilBlendMode;
|
||||
EStencilShape mStencilShape;
|
||||
F32 mStencilMin;
|
||||
F32 mStencilMax;
|
||||
|
||||
S32 mStencilCenterX;
|
||||
S32 mStencilCenterY;
|
||||
S32 mStencilWidth;
|
||||
F32 mStencilGamma;
|
||||
|
||||
F32 mStencilWavelength;
|
||||
F32 mStencilSine;
|
||||
F32 mStencilCosine;
|
||||
|
||||
F32 mStencilStartX;
|
||||
F32 mStencilStartY;
|
||||
F32 mStencilGradX;
|
||||
F32 mStencilGradY;
|
||||
F32 mStencilGradN;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -310,6 +310,7 @@ set(viewer_SOURCE_FILES
|
|||
llfilteredwearablelist.cpp
|
||||
llfirstuse.cpp
|
||||
llflexibleobject.cpp
|
||||
llflickrconnect.cpp
|
||||
llfloaterabout.cpp
|
||||
llfloaterbvhpreview.cpp
|
||||
llfloaterauction.cpp
|
||||
|
|
@ -318,6 +319,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloateravatarpicker.cpp
|
||||
llfloateravatartextures.cpp
|
||||
llfloaterbeacons.cpp
|
||||
llfloaterbigpreview.cpp
|
||||
llfloaterbuildoptions.cpp
|
||||
llfloaterbulkpermission.cpp
|
||||
llfloaterbump.cpp
|
||||
|
|
@ -339,6 +341,8 @@ set(viewer_SOURCE_FILES
|
|||
llfloatereditwater.cpp
|
||||
llfloaterenvironmentsettings.cpp
|
||||
llfloaterevent.cpp
|
||||
llfloaterfacebook.cpp
|
||||
llfloaterflickr.cpp
|
||||
llfloaterfonttest.cpp
|
||||
llfloatergesture.cpp
|
||||
llfloatergodtools.cpp
|
||||
|
|
@ -391,7 +395,6 @@ set(viewer_SOURCE_FILES
|
|||
llfloatersettingsdebug.cpp
|
||||
llfloatersidepanelcontainer.cpp
|
||||
llfloatersnapshot.cpp
|
||||
llfloatersocial.cpp
|
||||
llfloatersounddevices.cpp
|
||||
llfloaterspellchecksettings.cpp
|
||||
llfloatertelehub.cpp
|
||||
|
|
@ -403,6 +406,7 @@ set(viewer_SOURCE_FILES
|
|||
llfloatertos.cpp
|
||||
llfloatertoybox.cpp
|
||||
llfloatertranslationsettings.cpp
|
||||
llfloatertwitter.cpp
|
||||
llfloateruipreview.cpp
|
||||
llfloaterurlentry.cpp
|
||||
llfloatervoiceeffect.cpp
|
||||
|
|
@ -440,6 +444,7 @@ set(viewer_SOURCE_FILES
|
|||
llhudrender.cpp
|
||||
llhudtext.cpp
|
||||
llhudview.cpp
|
||||
llimagefiltersmanager.cpp
|
||||
llimhandler.cpp
|
||||
llimview.cpp
|
||||
llinspect.cpp
|
||||
|
|
@ -683,6 +688,7 @@ set(viewer_SOURCE_FILES
|
|||
lltransientdockablefloater.cpp
|
||||
lltransientfloatermgr.cpp
|
||||
lltranslate.cpp
|
||||
lltwitterconnect.cpp
|
||||
lluilistener.cpp
|
||||
lluploaddialog.cpp
|
||||
lluploadfloaterobservers.cpp
|
||||
|
|
@ -1028,6 +1034,7 @@ set(viewer_HEADER_FILES
|
|||
llfilteredwearablelist.h
|
||||
llfirstuse.h
|
||||
llflexibleobject.h
|
||||
llflickrconnect.h
|
||||
llfloaterabout.h
|
||||
llfloaterbvhpreview.h
|
||||
llfloaterauction.h
|
||||
|
|
@ -1036,6 +1043,7 @@ set(viewer_HEADER_FILES
|
|||
llfloateravatarpicker.h
|
||||
llfloateravatartextures.h
|
||||
llfloaterbeacons.h
|
||||
llfloaterbigpreview.h
|
||||
llfloaterbuildoptions.h
|
||||
llfloaterbulkpermission.h
|
||||
llfloaterbump.h
|
||||
|
|
@ -1057,6 +1065,8 @@ set(viewer_HEADER_FILES
|
|||
llfloatereditwater.h
|
||||
llfloaterenvironmentsettings.h
|
||||
llfloaterevent.h
|
||||
llfloaterfacebook.h
|
||||
llfloaterflickr.h
|
||||
llfloaterfonttest.h
|
||||
llfloatergesture.h
|
||||
llfloatergodtools.h
|
||||
|
|
@ -1112,7 +1122,6 @@ set(viewer_HEADER_FILES
|
|||
llfloatersettingsdebug.h
|
||||
llfloatersidepanelcontainer.h
|
||||
llfloatersnapshot.h
|
||||
llfloatersocial.h
|
||||
llfloatersounddevices.h
|
||||
llfloaterspellchecksettings.h
|
||||
llfloatertelehub.h
|
||||
|
|
@ -1124,6 +1133,7 @@ set(viewer_HEADER_FILES
|
|||
llfloatertos.h
|
||||
llfloatertoybox.h
|
||||
llfloatertranslationsettings.h
|
||||
llfloatertwitter.h
|
||||
llfloateruipreview.h
|
||||
llfloaterurlentry.h
|
||||
llfloatervoiceeffect.h
|
||||
|
|
@ -1160,6 +1170,7 @@ set(viewer_HEADER_FILES
|
|||
llhudrender.h
|
||||
llhudtext.h
|
||||
llhudview.h
|
||||
llimagefiltersmanager.h
|
||||
llimview.h
|
||||
llinspect.h
|
||||
llinspectavatar.h
|
||||
|
|
@ -1391,6 +1402,7 @@ set(viewer_HEADER_FILES
|
|||
lltransientdockablefloater.h
|
||||
lltransientfloatermgr.h
|
||||
lltranslate.h
|
||||
lltwitterconnect.h
|
||||
lluiconstants.h
|
||||
lluilistener.h
|
||||
lluploaddialog.h
|
||||
|
|
|
|||
|
|
@ -224,15 +224,35 @@
|
|||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="snapshot"
|
||||
/>
|
||||
<command name="social"
|
||||
<command name="facebook"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Social_Icon"
|
||||
label_ref="Command_Social_Label"
|
||||
tooltip_ref="Command_Social_Tooltip"
|
||||
icon="Command_Facebook_Icon"
|
||||
label_ref="Command_Facebook_Label"
|
||||
tooltip_ref="Command_Facebook_Tooltip"
|
||||
execute_function="Floater.ToggleOrBringToFront"
|
||||
execute_parameters="social"
|
||||
execute_parameters="facebook"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="social"
|
||||
is_running_parameters="facebook"
|
||||
/>
|
||||
<command name="flickr"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Flickr_Icon"
|
||||
label_ref="Command_Flickr_Label"
|
||||
tooltip_ref="Command_Flickr_Tooltip"
|
||||
execute_function="Floater.ToggleOrBringToFront"
|
||||
execute_parameters="flickr"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="flickr"
|
||||
/>
|
||||
<command name="twitter"
|
||||
available_in_toybox="true"
|
||||
icon="Command_Twitter_Icon"
|
||||
label_ref="Command_Twitter_Label"
|
||||
tooltip_ref="Command_Twitter_Tooltip"
|
||||
execute_function="Floater.ToggleOrBringToFront"
|
||||
execute_parameters="twitter"
|
||||
is_running_function="Floater.IsOpen"
|
||||
is_running_parameters="twitter"
|
||||
/>
|
||||
<command name="speak"
|
||||
available_in_toybox="true"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.8</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.8</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.3</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>10.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.1</real>
|
||||
<real>0.1</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>3.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>add</string>
|
||||
<real>0.5</real>
|
||||
<real>0.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>-1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.1</real>
|
||||
<real>0.1</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.5</real>
|
||||
<real>5.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.6</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>-1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>5.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.6</real>
|
||||
<real>0.6</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.5</real>
|
||||
<real>-0.5</real>
|
||||
<real>0.10</real>
|
||||
<real>20.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.7</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.6</real>
|
||||
<real>-0.6</real>
|
||||
<real>0.05</real>
|
||||
<real>20.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.7</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>0.4</real>
|
||||
<real>-0.4</real>
|
||||
<real>0.025</real>
|
||||
<real>20.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>colorize</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.7</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.02</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.02</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>saturate</string>
|
||||
<real>1.2</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>0.0</real>
|
||||
<real>0.25</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.25</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>sharpen</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>-0.25</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>gradient</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.25</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>2Dsine</string>
|
||||
<real>0.02</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.01</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>0.8</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>fade</string>
|
||||
<real>0.5</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>4.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>sepia</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.4</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>add</string>
|
||||
<real>-0.8</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>fade</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>1.2</real>
|
||||
<real>3.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.05</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>grayscale</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>contrast</string>
|
||||
<real>1.1</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>vignette</string>
|
||||
<string>blend</string>
|
||||
<real>1.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
<real>2.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
<llsd>
|
||||
<array>
|
||||
<array>
|
||||
<string>linearize</string>
|
||||
<real>0.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>darken</string>
|
||||
<real>0.15</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>stencil</string>
|
||||
<string>uniform</string>
|
||||
<string>add</string>
|
||||
<real>0.0</real>
|
||||
<real>0.5</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>screen</string>
|
||||
<string>line</string>
|
||||
<real>0.02</real>
|
||||
<real>0.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>gamma</string>
|
||||
<real>0.25</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
<real>1.0</real>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
<array>
|
||||
<string>blur</string>
|
||||
</array>
|
||||
</array>
|
||||
</llsd>
|
||||
|
|
@ -14313,6 +14313,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotFiltersEnabled</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Enable filters in the Snapshot Advanced panel (experimental).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>SnapshotFormat</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
@ -16599,7 +16610,7 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>SocialPhotoResolution</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Default resolution when sharing photo using the social floater</string>
|
||||
<string>Default resolution when sharing photo using the social floaters</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llflickrconnect.h"
|
||||
#include "lltwitterconnect.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
|
|
@ -58,7 +60,7 @@ void log_facebook_connect_error(const std::string& request, U32 status, const st
|
|||
}
|
||||
}
|
||||
|
||||
void toast_user_for_success()
|
||||
void toast_user_for_facebook_success()
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("facebook_post_success");
|
||||
|
|
@ -74,23 +76,46 @@ public:
|
|||
|
||||
bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web)
|
||||
{
|
||||
if (tokens.size() > 0)
|
||||
if (tokens.size() >= 1)
|
||||
{
|
||||
if (tokens[0].asString() == "connect")
|
||||
{
|
||||
// this command probably came from the fbc_web browser, so close it
|
||||
LLFloater* fbc_web = LLFloaterReg::getInstance("fbc_web");
|
||||
if (fbc_web)
|
||||
if (tokens.size() >= 2 && tokens[1].asString() == "flickr")
|
||||
{
|
||||
fbc_web->closeFloater();
|
||||
}
|
||||
// this command probably came from the flickr_web browser, so close it
|
||||
LLFloaterReg::hideInstance("flickr_web");
|
||||
|
||||
// connect to facebook
|
||||
if (query_map.has("code"))
|
||||
{
|
||||
LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
|
||||
// connect to flickr
|
||||
if (query_map.has("oauth_token"))
|
||||
{
|
||||
LLFlickrConnect::instance().connectToFlickr(query_map["oauth_token"], query_map.get("oauth_verifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (tokens.size() >= 2 && tokens[1].asString() == "twitter")
|
||||
{
|
||||
// this command probably came from the twitter_web browser, so close it
|
||||
LLFloaterReg::hideInstance("twitter_web");
|
||||
|
||||
// connect to twitter
|
||||
if (query_map.has("oauth_token"))
|
||||
{
|
||||
LLTwitterConnect::instance().connectToTwitter(query_map["oauth_token"], query_map.get("oauth_verifier"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else //if (tokens.size() >= 2 && tokens[1].asString() == "facebook")
|
||||
{
|
||||
// this command probably came from the fbc_web browser, so close it
|
||||
LLFloaterReg::hideInstance("fbc_web");
|
||||
|
||||
// connect to facebook
|
||||
if (query_map.has("code"))
|
||||
{
|
||||
LLFacebookConnect::instance().connectToFacebook(query_map["code"], query_map.get("state"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -156,7 +181,7 @@ public:
|
|||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
toast_user_for_success();
|
||||
toast_user_for_facebook_success();
|
||||
LL_DEBUGS("FacebookConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
|
||||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_POSTED);
|
||||
}
|
||||
|
|
@ -302,9 +327,16 @@ public:
|
|||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
LL_INFOS() << "Facebook: Info received" << LL_ENDL;
|
||||
LL_DEBUGS("FacebookConnect") << "Getting Facebook info successful. info: " << getContent() << LL_ENDL;
|
||||
LLFacebookConnect::instance().storeInfo(getContent());
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FacebookConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFacebookConnect::instance().openFacebookWeb(location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -371,10 +403,12 @@ void LLFacebookConnect::openFacebookWeb(std::string url)
|
|||
{
|
||||
// Open the URL in an internal browser window without navigation UI
|
||||
LLFloaterWebContent::Params p;
|
||||
p.url(url).show_chrome(true);
|
||||
p.url(url).allow_address_entry(false);
|
||||
p.url(url).allow_back_forward_navigation(false);
|
||||
p.url(url).trusted_content(true);
|
||||
p.url(url);
|
||||
p.show_chrome(true);
|
||||
p.allow_address_entry(false);
|
||||
p.allow_back_forward_navigation(false);
|
||||
p.trusted_content(true);
|
||||
p.clean_browser(true);
|
||||
LLFloater *floater = LLFloaterReg::showInstance("fbc_web", p);
|
||||
//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
|
||||
//So when showing the internal web browser, set focus to it's containing floater "fbc_web". When a mouse event
|
||||
|
|
@ -391,7 +425,8 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b
|
|||
LLViewerRegion *regionp = gAgent.getRegion();
|
||||
if (regionp)
|
||||
{
|
||||
url = regionp->getCapability("FacebookConnect");
|
||||
//url = "http://pdp15.lindenlab.com/fbc/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
|
||||
url = regionp->getCapability("FacebookConnect");
|
||||
url += route;
|
||||
|
||||
if (include_read_from_master && mReadFromMaster)
|
||||
|
|
@ -406,9 +441,13 @@ void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const st
|
|||
{
|
||||
LLSD body;
|
||||
if (!auth_code.empty())
|
||||
{
|
||||
body["code"] = auth_code;
|
||||
}
|
||||
if (!auth_state.empty())
|
||||
{
|
||||
body["state"] = auth_state;
|
||||
}
|
||||
|
||||
LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder());
|
||||
}
|
||||
|
|
@ -452,15 +491,25 @@ void LLFacebookConnect::postCheckin(const std::string& location, const std::stri
|
|||
{
|
||||
LLSD body;
|
||||
if (!location.empty())
|
||||
{
|
||||
body["location"] = location;
|
||||
}
|
||||
if (!name.empty())
|
||||
{
|
||||
body["name"] = name;
|
||||
}
|
||||
if (!description.empty())
|
||||
{
|
||||
body["description"] = description;
|
||||
}
|
||||
if (!image.empty())
|
||||
{
|
||||
body["image"] = image;
|
||||
}
|
||||
if (!message.empty())
|
||||
{
|
||||
body["message"] = message;
|
||||
}
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder());
|
||||
|
|
@ -507,7 +556,7 @@ void LLFacebookConnect::sharePhoto(LLPointer<LLImageFormatted> image, const std:
|
|||
<< caption << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"snapshot." << imageFormat << "\"\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
|
||||
<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
|
||||
|
||||
// Insert the image data.
|
||||
|
|
@ -599,12 +648,13 @@ void LLFacebookConnect::setConnectionState(LLFacebookConnect::EConnectionState c
|
|||
|
||||
if (mConnectionState != connection_state)
|
||||
{
|
||||
// set the connection state before notifying watchers
|
||||
mConnectionState = connection_state;
|
||||
|
||||
LLSD state_info;
|
||||
state_info["enum"] = connection_state;
|
||||
sStateWatcher->post(state_info);
|
||||
}
|
||||
|
||||
mConnectionState = connection_state;
|
||||
}
|
||||
|
||||
void LLFacebookConnect::setConnected(bool connected)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ private:
|
|||
LLFacebookConnect();
|
||||
~LLFacebookConnect() {};
|
||||
std::string getFacebookConnectURL(const std::string& route = "", bool include_read_from_master = false);
|
||||
|
||||
|
||||
EConnectionState mConnectionState;
|
||||
BOOL mConnected;
|
||||
LLSD mInfo;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,8 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
|
|||
BOOL res = TRUE;
|
||||
switch (filter)
|
||||
{
|
||||
case FFLOAD_ALL:
|
||||
case FFLOAD_ALL:
|
||||
case FFLOAD_EXE:
|
||||
mOFN.lpstrFilter = L"All Files (*.*)\0*.*\0" \
|
||||
SOUND_FILTER \
|
||||
IMAGE_FILTER \
|
||||
|
|
@ -650,6 +651,10 @@ std::vector<std::string>* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //
|
|||
allowedv->push_back("tpic");
|
||||
allowedv->push_back("png");
|
||||
break;
|
||||
case FFLOAD_EXE:
|
||||
allowedv->push_back("app");
|
||||
allowedv->push_back("exe");
|
||||
break;
|
||||
case FFLOAD_WAV:
|
||||
allowedv->push_back("wav");
|
||||
break;
|
||||
|
|
@ -881,7 +886,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
|||
mPickOptions &= ~F_FILE;
|
||||
}
|
||||
|
||||
if(filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
|
||||
if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
|
||||
{
|
||||
mPickOptions |= F_NAV_SUPPORT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ public:
|
|||
FFLOAD_SCRIPT = 11,
|
||||
FFLOAD_DICTIONARY = 12,
|
||||
FFLOAD_DIRECTORY = 13, //To call from lldirpicker.
|
||||
FFLOAD_EXE = 14, // Note: EXE will be treated as ALL on Windows and Linux but not on Darwin
|
||||
|
||||
// Firestorm additions
|
||||
FFLOAD_IMPORT = 50
|
||||
|
|
|
|||
|
|
@ -0,0 +1,509 @@
|
|||
/**
|
||||
* @file llflickrconnect.h
|
||||
* @author Merov, Cho
|
||||
* @brief Connection to Flickr Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llflickrconnect.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcommandhandler.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "lltrans.h"
|
||||
#include "llevents.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
#include "llfloaterwebcontent.h"
|
||||
#include "llfloaterreg.h"
|
||||
|
||||
boost::scoped_ptr<LLEventPump> LLFlickrConnect::sStateWatcher(new LLEventStream("FlickrConnectState"));
|
||||
boost::scoped_ptr<LLEventPump> LLFlickrConnect::sInfoWatcher(new LLEventStream("FlickrConnectInfo"));
|
||||
boost::scoped_ptr<LLEventPump> LLFlickrConnect::sContentWatcher(new LLEventStream("FlickrConnectContent"));
|
||||
|
||||
// Local functions
|
||||
void log_flickr_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
|
||||
{
|
||||
// Note: 302 (redirect) is *not* an error that warrants logging
|
||||
if (status != 302)
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void toast_user_for_flickr_success()
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("flickr_post_success");
|
||||
LLNotificationsUtil::add("FlickrConnect", args);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFlickrConnectResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFlickrConnectResponder);
|
||||
public:
|
||||
|
||||
LLFlickrConnectResponder()
|
||||
{
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_DEBUGS("FlickrConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFlickrConnect::instance().openFlickrWeb(location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_flickr_connect_error("Connect", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFlickrShareResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFlickrShareResponder);
|
||||
public:
|
||||
|
||||
LLFlickrShareResponder()
|
||||
{
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTING);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
toast_user_for_flickr_success();
|
||||
LL_DEBUGS("FlickrConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POSTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFlickrConnect::instance().openFlickrWeb(location);
|
||||
}
|
||||
}
|
||||
else if ( HTTP_NOT_FOUND == getStatus() )
|
||||
{
|
||||
LLFlickrConnect::instance().connectToFlickr();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_POST_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_flickr_connect_error("Share", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFlickrDisconnectResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFlickrDisconnectResponder);
|
||||
public:
|
||||
|
||||
LLFlickrDisconnectResponder()
|
||||
{
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECTING);
|
||||
}
|
||||
|
||||
void setUserDisconnected()
|
||||
{
|
||||
// Clear data
|
||||
LLFlickrConnect::instance().clearInfo();
|
||||
|
||||
//Notify state change
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_DEBUGS("FlickrConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
|
||||
setUserDisconnected();
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
//User not found so already disconnected
|
||||
if ( HTTP_NOT_FOUND == getStatus() )
|
||||
{
|
||||
LL_DEBUGS("FlickrConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
|
||||
setUserDisconnected();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_DISCONNECT_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_flickr_connect_error("Disconnect", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFlickrConnectedResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFlickrConnectedResponder);
|
||||
public:
|
||||
|
||||
LLFlickrConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
|
||||
{
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_DEBUGS("FlickrConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
// show the facebook login page if not connected yet
|
||||
if ( HTTP_NOT_FOUND == getStatus() )
|
||||
{
|
||||
LL_DEBUGS("FlickrConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
|
||||
if (mAutoConnect)
|
||||
{
|
||||
LLFlickrConnect::instance().connectToFlickr();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_NOT_CONNECTED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_flickr_connect_error("Connected", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool mAutoConnect;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLFlickrInfoResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLFlickrInfoResponder);
|
||||
public:
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_INFOS("FlickrConnect") << "Flickr: Info received" << LL_ENDL;
|
||||
LL_DEBUGS("FlickrConnect") << "Getting Flickr info successful. " << dumpResponse() << LL_ENDL;
|
||||
LLFlickrConnect::instance().storeInfo(getContent());
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFlickrConnect::instance().openFlickrWeb(location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("FlickrConnect") << dumpResponse() << LL_ENDL;
|
||||
const LLSD& content = getContent();
|
||||
log_flickr_connect_error("Info", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
LLFlickrConnect::LLFlickrConnect()
|
||||
: mConnectionState(FLICKR_NOT_CONNECTED),
|
||||
mConnected(false),
|
||||
mInfo(),
|
||||
mRefreshInfo(false),
|
||||
mReadFromMaster(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLFlickrConnect::openFlickrWeb(std::string url)
|
||||
{
|
||||
// Open the URL in an internal browser window without navigation UI
|
||||
LLFloaterWebContent::Params p;
|
||||
p.url(url);
|
||||
p.show_chrome(true);
|
||||
p.allow_address_entry(false);
|
||||
p.allow_back_forward_navigation(false);
|
||||
p.trusted_content(true);
|
||||
p.clean_browser(true);
|
||||
LLFloater *floater = LLFloaterReg::showInstance("flickr_web", p);
|
||||
//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
|
||||
//So when showing the internal web browser, set focus to it's containing floater "flickr_web". When a mouse event
|
||||
//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
|
||||
//flickr_web floater contains the "webbrowser" panel. JIRA: ACME-744
|
||||
gFocusMgr.setKeyboardFocus( floater );
|
||||
|
||||
//LLUrlAction::openURLExternal(url);
|
||||
}
|
||||
|
||||
std::string LLFlickrConnect::getFlickrConnectURL(const std::string& route, bool include_read_from_master)
|
||||
{
|
||||
std::string url("");
|
||||
LLViewerRegion *regionp = gAgent.getRegion();
|
||||
if (regionp)
|
||||
{
|
||||
//url = "http://pdp15.lindenlab.com/flickr/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
|
||||
url = regionp->getCapability("FlickrConnect");
|
||||
url += route;
|
||||
|
||||
if (include_read_from_master && mReadFromMaster)
|
||||
{
|
||||
url += "?read_from_master=true";
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
void LLFlickrConnect::connectToFlickr(const std::string& request_token, const std::string& oauth_verifier)
|
||||
{
|
||||
LLSD body;
|
||||
if (!request_token.empty())
|
||||
body["request_token"] = request_token;
|
||||
if (!oauth_verifier.empty())
|
||||
body["oauth_verifier"] = oauth_verifier;
|
||||
|
||||
LLHTTPClient::put(getFlickrConnectURL("/connection"), body, new LLFlickrConnectResponder());
|
||||
}
|
||||
|
||||
void LLFlickrConnect::disconnectFromFlickr()
|
||||
{
|
||||
LLHTTPClient::del(getFlickrConnectURL("/connection"), new LLFlickrDisconnectResponder());
|
||||
}
|
||||
|
||||
void LLFlickrConnect::checkConnectionToFlickr(bool auto_connect)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getFlickrConnectURL("/connection", true), new LLFlickrConnectedResponder(auto_connect),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
|
||||
void LLFlickrConnect::loadFlickrInfo()
|
||||
{
|
||||
if(mRefreshInfo)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getFlickrConnectURL("/info", true), new LLFlickrInfoResponder(),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrConnect::uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
|
||||
{
|
||||
LLSD body;
|
||||
body["image"] = image_url;
|
||||
body["title"] = title;
|
||||
body["description"] = description;
|
||||
body["tags"] = tags;
|
||||
body["safety_level"] = safety_level;
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getFlickrConnectURL("/share/photo", true), body, new LLFlickrShareResponder());
|
||||
}
|
||||
|
||||
void LLFlickrConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level)
|
||||
{
|
||||
std::string imageFormat;
|
||||
if (dynamic_cast<LLImagePNG*>(image.get()))
|
||||
{
|
||||
imageFormat = "png";
|
||||
}
|
||||
else if (dynamic_cast<LLImageJPEG*>(image.get()))
|
||||
{
|
||||
imageFormat = "jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Image to upload is not a PNG or JPEG" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
// All this code is mostly copied from LLWebProfile::post()
|
||||
const std::string boundary = "----------------------------0123abcdefab";
|
||||
|
||||
LLSD headers;
|
||||
headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
|
||||
|
||||
std::ostringstream body;
|
||||
|
||||
// *NOTE: The order seems to matter.
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"title\"\r\n\r\n"
|
||||
<< title << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"description\"\r\n\r\n"
|
||||
<< description << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"tags\"\r\n\r\n"
|
||||
<< tags << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"safety_level\"\r\n\r\n"
|
||||
<< safety_level << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
|
||||
<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
|
||||
|
||||
// Insert the image data.
|
||||
// *FIX: Treating this as a string will probably screw it up ...
|
||||
U8* image_data = image->getData();
|
||||
for (S32 i = 0; i < image->getDataSize(); ++i)
|
||||
{
|
||||
body << image_data[i];
|
||||
}
|
||||
|
||||
body << "\r\n--" << boundary << "--\r\n";
|
||||
|
||||
// postRaw() takes ownership of the buffer and releases it later.
|
||||
size_t size = body.str().size();
|
||||
U8 *data = new U8[size];
|
||||
memcpy(data, body.str().data(), size);
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::postRaw(getFlickrConnectURL("/share/photo", true), data, size, new LLFlickrShareResponder(), headers);
|
||||
}
|
||||
|
||||
void LLFlickrConnect::storeInfo(const LLSD& info)
|
||||
{
|
||||
mInfo = info;
|
||||
mRefreshInfo = false;
|
||||
|
||||
sInfoWatcher->post(info);
|
||||
}
|
||||
|
||||
const LLSD& LLFlickrConnect::getInfo() const
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
void LLFlickrConnect::clearInfo()
|
||||
{
|
||||
mInfo = LLSD();
|
||||
}
|
||||
|
||||
void LLFlickrConnect::setDataDirty()
|
||||
{
|
||||
mRefreshInfo = true;
|
||||
}
|
||||
|
||||
void LLFlickrConnect::setConnectionState(LLFlickrConnect::EConnectionState connection_state)
|
||||
{
|
||||
if(connection_state == FLICKR_CONNECTED)
|
||||
{
|
||||
mReadFromMaster = true;
|
||||
setConnected(true);
|
||||
setDataDirty();
|
||||
}
|
||||
else if(connection_state == FLICKR_NOT_CONNECTED)
|
||||
{
|
||||
setConnected(false);
|
||||
}
|
||||
else if(connection_state == FLICKR_POSTED)
|
||||
{
|
||||
mReadFromMaster = false;
|
||||
}
|
||||
|
||||
if (mConnectionState != connection_state)
|
||||
{
|
||||
// set the connection state before notifying watchers
|
||||
mConnectionState = connection_state;
|
||||
|
||||
LLSD state_info;
|
||||
state_info["enum"] = connection_state;
|
||||
sStateWatcher->post(state_info);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrConnect::setConnected(bool connected)
|
||||
{
|
||||
mConnected = connected;
|
||||
}
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* @file llflickrconnect.h
|
||||
* @author Merov, Cho
|
||||
* @brief Connection to Flickr Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFLICKRCONNECT_H
|
||||
#define LL_LLFLICKRCONNECT_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "llimage.h"
|
||||
|
||||
class LLEventPump;
|
||||
|
||||
/**
|
||||
* @class LLFlickrConnect
|
||||
*
|
||||
* Manages authentication to, and interaction with, a web service allowing the
|
||||
* the viewer to upload photos to Flickr.
|
||||
*/
|
||||
class LLFlickrConnect : public LLSingleton<LLFlickrConnect>
|
||||
{
|
||||
LOG_CLASS(LLFlickrConnect);
|
||||
public:
|
||||
enum EConnectionState
|
||||
{
|
||||
FLICKR_NOT_CONNECTED = 0,
|
||||
FLICKR_CONNECTION_IN_PROGRESS = 1,
|
||||
FLICKR_CONNECTED = 2,
|
||||
FLICKR_CONNECTION_FAILED = 3,
|
||||
FLICKR_POSTING = 4,
|
||||
FLICKR_POSTED = 5,
|
||||
FLICKR_POST_FAILED = 6,
|
||||
FLICKR_DISCONNECTING = 7,
|
||||
FLICKR_DISCONNECT_FAILED = 8
|
||||
};
|
||||
|
||||
void connectToFlickr(const std::string& request_token = "", const std::string& oauth_verifier = ""); // Initiate the complete Flickr connection. Please use checkConnectionToFlickr() in normal use.
|
||||
void disconnectFromFlickr(); // Disconnect from the Flickr service.
|
||||
void checkConnectionToFlickr(bool auto_connect = false); // Check if an access token is available on the Flickr service. If not, call connectToFlickr().
|
||||
|
||||
void loadFlickrInfo();
|
||||
void uploadPhoto(const std::string& image_url, const std::string& title, const std::string& description, const std::string& tags, int safety_level);
|
||||
void uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& title, const std::string& description, const std::string& tags, int safety_level);
|
||||
|
||||
void storeInfo(const LLSD& info);
|
||||
const LLSD& getInfo() const;
|
||||
void clearInfo();
|
||||
void setDataDirty();
|
||||
|
||||
void setConnectionState(EConnectionState connection_state);
|
||||
void setConnected(bool connected);
|
||||
bool isConnected() { return mConnected; }
|
||||
bool isTransactionOngoing() { return ((mConnectionState == FLICKR_CONNECTION_IN_PROGRESS) || (mConnectionState == FLICKR_POSTING) || (mConnectionState == FLICKR_DISCONNECTING)); }
|
||||
EConnectionState getConnectionState() { return mConnectionState; }
|
||||
|
||||
void openFlickrWeb(std::string url);
|
||||
|
||||
private:
|
||||
friend class LLSingleton<LLFlickrConnect>;
|
||||
|
||||
LLFlickrConnect();
|
||||
~LLFlickrConnect() {};
|
||||
std::string getFlickrConnectURL(const std::string& route = "", bool include_read_from_master = false);
|
||||
|
||||
EConnectionState mConnectionState;
|
||||
BOOL mConnected;
|
||||
LLSD mInfo;
|
||||
bool mRefreshInfo;
|
||||
bool mReadFromMaster;
|
||||
|
||||
static boost::scoped_ptr<LLEventPump> sStateWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sInfoWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sContentWatcher;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLICKRCONNECT_H
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* @file llfloaterbigpreview.cpp
|
||||
* @brief Display of extended (big) preview for snapshots and SL Share
|
||||
* @author merov@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloaterbigpreview.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
|
||||
///////////////////////
|
||||
//LLFloaterBigPreview//
|
||||
///////////////////////
|
||||
|
||||
LLFloaterBigPreview::LLFloaterBigPreview(const LLSD& key) : LLFloater(key),
|
||||
mPreviewPlaceholder(NULL),
|
||||
mFloaterOwner(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLFloaterBigPreview::~LLFloaterBigPreview()
|
||||
{
|
||||
if (mPreviewHandle.get())
|
||||
{
|
||||
mPreviewHandle.get()->die();
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterBigPreview::onCancel()
|
||||
{
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
void LLFloaterBigPreview::closeOnFloaterOwnerClosing(LLFloater* floaterp)
|
||||
{
|
||||
if (isFloaterOwner(floaterp))
|
||||
{
|
||||
closeFloater();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLFloaterBigPreview::postBuild()
|
||||
{
|
||||
mPreviewPlaceholder = getChild<LLUICtrl>("big_preview_placeholder");
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
|
||||
void LLFloaterBigPreview::draw()
|
||||
{
|
||||
LLFloater::draw();
|
||||
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
|
||||
// Display the preview if one is available
|
||||
if (previewp && previewp->getBigThumbnailImage())
|
||||
{
|
||||
// Get the preview rect
|
||||
const LLRect& preview_rect = mPreviewPlaceholder->getRect();
|
||||
|
||||
// Get the preview texture size
|
||||
S32 thumbnail_w = previewp->getBigThumbnailWidth();
|
||||
S32 thumbnail_h = previewp->getBigThumbnailHeight();
|
||||
|
||||
// Compute the scaling ratio and the size of the final texture in the rect: we want to prevent anisotropic scaling (distorted in x and y)
|
||||
F32 ratio = llmax((F32)(thumbnail_w)/(F32)(preview_rect.getWidth()), (F32)(thumbnail_h)/(F32)(preview_rect.getHeight()));
|
||||
thumbnail_w = (S32)((F32)(thumbnail_w)/ratio);
|
||||
thumbnail_h = (S32)((F32)(thumbnail_h)/ratio);
|
||||
|
||||
// Compute the preview offset within the preview rect: we want to center that preview in the available rect
|
||||
const S32 local_offset_x = (preview_rect.getWidth() - thumbnail_w) / 2 ;
|
||||
const S32 local_offset_y = (preview_rect.getHeight() - thumbnail_h) / 2 ;
|
||||
|
||||
// Compute preview offset within the floater rect
|
||||
S32 offset_x = preview_rect.mLeft + local_offset_x;
|
||||
S32 offset_y = preview_rect.mBottom + local_offset_y;
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
// Apply floater transparency to the texture unless the floater is focused.
|
||||
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
|
||||
LLColor4 color = LLColor4::white;
|
||||
|
||||
// Draw the preview texture
|
||||
gl_draw_scaled_image(offset_x, offset_y,
|
||||
thumbnail_w, thumbnail_h,
|
||||
previewp->getBigThumbnailImage(), color % alpha);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* @file llfloaterbigpreview.h
|
||||
* @brief Display of extended (big) preview for snapshots and SL Share
|
||||
* @author merov@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_LLFLOATERBIGPREVIEW_H
|
||||
#define LL_LLFLOATERBIGPREVIEW_H
|
||||
|
||||
#include "llfloater.h"
|
||||
|
||||
class LLFloaterBigPreview : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterBigPreview(const LLSD& key);
|
||||
~LLFloaterBigPreview();
|
||||
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onCancel();
|
||||
|
||||
void setPreview(LLView* previewp) { mPreviewHandle = previewp->getHandle(); }
|
||||
void setFloaterOwner(LLFloater* floaterp) { mFloaterOwner = floaterp; }
|
||||
bool isFloaterOwner(LLFloater* floaterp) const { return (mFloaterOwner == floaterp); }
|
||||
void closeOnFloaterOwnerClosing(LLFloater* floaterp);
|
||||
|
||||
private:
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
LLUICtrl* mPreviewPlaceholder;
|
||||
LLFloater* mFloaterOwner;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERBIGPREVIEW_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @file llfloatersocial.h
|
||||
* @brief Header file for llfloatersocial
|
||||
* @file llfloaterfacebook.h
|
||||
* @brief Header file for llfloaterfacebook
|
||||
* @author Gilbert@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
|
|
@ -24,9 +24,10 @@
|
|||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_LLFLOATERSOCIAL_H
|
||||
#define LL_LLFLOATERSOCIAL_H
|
||||
#ifndef LL_LLFLOATERFACEBOOK_H
|
||||
#define LL_LLFLOATERFACEBOOK_H
|
||||
|
||||
#include "llcallingcard.h"
|
||||
#include "llfloater.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llviewertexture.h"
|
||||
|
|
@ -34,11 +35,13 @@
|
|||
class LLIconCtrl;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSnapshotLivePreview;
|
||||
class LLAvatarList;
|
||||
class LLFloaterBigPreview;
|
||||
|
||||
class LLSocialStatusPanel : public LLPanel
|
||||
class LLFacebookStatusPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialStatusPanel();
|
||||
LLFacebookStatusPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onSend();
|
||||
|
|
@ -53,19 +56,21 @@ private:
|
|||
LLUICtrl* mCancelButton;
|
||||
};
|
||||
|
||||
class LLSocialPhotoPanel : public LLPanel
|
||||
class LLFacebookPhotoPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialPhotoPanel();
|
||||
~LLSocialPhotoPanel();
|
||||
LLFacebookPhotoPanel();
|
||||
~LLFacebookPhotoPanel();
|
||||
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
LLSnapshotLivePreview* getPreviewView();
|
||||
void onVisibilityChanged(const LLSD& new_visibility);
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
void onClickBigPreview();
|
||||
void onClickNewSnapshot();
|
||||
void onSend();
|
||||
S32 notify(const LLSD& info);
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendPhoto();
|
||||
|
|
@ -77,22 +82,31 @@ public:
|
|||
LLUICtrl* getRefreshBtn();
|
||||
|
||||
private:
|
||||
bool isPreviewVisible();
|
||||
void attachPreview();
|
||||
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
|
||||
LLUICtrl * mSnapshotPanel;
|
||||
LLUICtrl * mResolutionComboBox;
|
||||
LLUICtrl * mFilterComboBox;
|
||||
LLUICtrl * mRefreshBtn;
|
||||
LLUICtrl * mWorkingLabel;
|
||||
LLUICtrl * mThumbnailPlaceholder;
|
||||
LLUICtrl * mCaptionTextBox;
|
||||
LLUICtrl * mPostButton;
|
||||
LLUICtrl* mCancelButton;
|
||||
LLUICtrl * mCancelButton;
|
||||
LLButton * mBtnPreview;
|
||||
|
||||
LLFloaterBigPreview * mBigPreviewFloater;
|
||||
|
||||
S32 mQuality; // Compression quality
|
||||
};
|
||||
|
||||
class LLSocialCheckinPanel : public LLPanel
|
||||
class LLFacebookCheckinPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLSocialCheckinPanel();
|
||||
LLFacebookCheckinPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onSend();
|
||||
|
|
@ -114,15 +128,34 @@ private:
|
|||
bool mReloadingMapTexture;
|
||||
};
|
||||
|
||||
class LLSocialAccountPanel : public LLPanel
|
||||
class LLFacebookFriendsPanel : public LLPanel, public LLFriendObserver
|
||||
{
|
||||
public:
|
||||
LLSocialAccountPanel();
|
||||
LLFacebookFriendsPanel();
|
||||
~LLFacebookFriendsPanel();
|
||||
BOOL postBuild();
|
||||
virtual void changed(U32 mask);
|
||||
|
||||
private:
|
||||
bool updateSuggestedFriendList();
|
||||
void showFriendsAccordionsIfNeeded();
|
||||
void updateFacebookList(bool visible);
|
||||
bool onConnectedToFacebook(const LLSD& data);
|
||||
|
||||
LLTextBox * mFriendsStatusCaption;
|
||||
LLAvatarList* mSecondLifeFriends;
|
||||
LLAvatarList* mSuggestedFriends;
|
||||
};
|
||||
|
||||
class LLFacebookAccountPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLFacebookAccountPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
private:
|
||||
void onVisibilityChanged(const LLSD& new_visibility);
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
bool onFacebookConnectStateChange(const LLSD& data);
|
||||
bool onFacebookConnectInfoChange();
|
||||
void onConnect();
|
||||
|
|
@ -141,24 +174,23 @@ private:
|
|||
LLUICtrl * mDisconnectButton;
|
||||
};
|
||||
|
||||
|
||||
class LLFloaterSocial : public LLFloater
|
||||
class LLFloaterFacebook : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterSocial(const LLSD& key);
|
||||
LLFloaterFacebook(const LLSD& key);
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onClose(bool app_quitting);
|
||||
void onCancel();
|
||||
|
||||
static void preUpdate();
|
||||
static void postUpdate();
|
||||
|
||||
void showPhotoPanel();
|
||||
|
||||
private:
|
||||
LLSocialPhotoPanel* mSocialPhotoPanel;
|
||||
LLFacebookPhotoPanel* mFacebookPhotoPanel;
|
||||
LLTextBox* mStatusErrorText;
|
||||
LLTextBox* mStatusLoadingText;
|
||||
LLUICtrl* mStatusLoadingIndicator;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERSOCIAL_H
|
||||
#endif // LL_LLFLOATERFACEBOOK_H
|
||||
|
||||
|
|
@ -0,0 +1,798 @@
|
|||
/**
|
||||
* @file llfloaterflickr.cpp
|
||||
* @brief Implementation of llfloaterflickr
|
||||
* @author cho@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloaterflickr.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentui.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llflickrconnect.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lliconctrl.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
#include "llresmgr.h" // LLLocale
|
||||
#include "llsdserialize.h"
|
||||
#include "llloadingindicator.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
#include "llfloaterbigpreview.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewermedia.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "llviewerparcelmgr.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
static LLPanelInjector<LLFlickrPhotoPanel> t_panel_photo("llflickrphotopanel");
|
||||
static LLPanelInjector<LLFlickrAccountPanel> t_panel_account("llflickraccountpanel");
|
||||
|
||||
const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
|
||||
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=flickr&utm_medium=photo&utm_campaign=slshare";
|
||||
const std::string DEFAULT_TAG_TEXT = "secondlife ";
|
||||
const std::string FLICKR_MACHINE_TAGS_NAMESPACE = "secondlife";
|
||||
|
||||
///////////////////////////
|
||||
//LLFlickrPhotoPanel///////
|
||||
///////////////////////////
|
||||
|
||||
LLFlickrPhotoPanel::LLFlickrPhotoPanel() :
|
||||
mSnapshotPanel(NULL),
|
||||
mResolutionComboBox(NULL),
|
||||
mRefreshBtn(NULL),
|
||||
mBtnPreview(NULL),
|
||||
mWorkingLabel(NULL),
|
||||
mThumbnailPlaceholder(NULL),
|
||||
mTitleTextBox(NULL),
|
||||
mDescriptionTextBox(NULL),
|
||||
mLocationCheckbox(NULL),
|
||||
mTagsTextBox(NULL),
|
||||
mRatingComboBox(NULL),
|
||||
mBigPreviewFloater(NULL),
|
||||
mPostButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLFlickrPhotoPanel::onSend, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLFlickrPhotoPanel::onClickNewSnapshot, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLFlickrPhotoPanel::onClickBigPreview, this));
|
||||
}
|
||||
|
||||
LLFlickrPhotoPanel::~LLFlickrPhotoPanel()
|
||||
{
|
||||
if(mPreviewHandle.get())
|
||||
{
|
||||
mPreviewHandle.get()->die();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLFlickrPhotoPanel::postBuild()
|
||||
{
|
||||
setVisibleCallback(boost::bind(&LLFlickrPhotoPanel::onVisibilityChange, this, _2));
|
||||
|
||||
mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
|
||||
mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
|
||||
mResolutionComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
|
||||
mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
|
||||
mFilterComboBox->setCommitCallback(boost::bind(&LLFlickrPhotoPanel::updateResolution, this, TRUE));
|
||||
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
|
||||
mBtnPreview = getChild<LLButton>("big_preview_btn");
|
||||
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
|
||||
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
|
||||
mTitleTextBox = getChild<LLUICtrl>("photo_title");
|
||||
mDescriptionTextBox = getChild<LLUICtrl>("photo_description");
|
||||
mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
|
||||
mTagsTextBox = getChild<LLUICtrl>("photo_tags");
|
||||
mTagsTextBox->setValue(DEFAULT_TAG_TEXT);
|
||||
mRatingComboBox = getChild<LLUICtrl>("rating_combobox");
|
||||
mPostButton = getChild<LLUICtrl>("post_photo_btn");
|
||||
mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
|
||||
mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
|
||||
// Update filter list
|
||||
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
|
||||
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
|
||||
for (U32 i = 0; i < filter_list.size(); i++)
|
||||
{
|
||||
filterbox->add(filter_list[i]);
|
||||
}
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
// virtual
|
||||
S32 LLFlickrPhotoPanel::notify(const LLSD& info)
|
||||
{
|
||||
if (info.has("snapshot-updating"))
|
||||
{
|
||||
// Disable the Post button and whatever else while the snapshot is not updated
|
||||
// updateControls();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.has("snapshot-updated"))
|
||||
{
|
||||
// Enable the send/post/save buttons.
|
||||
updateControls();
|
||||
|
||||
// The refresh button is initially hidden. We show it after the first update,
|
||||
// i.e. after snapshot is taken
|
||||
LLUICtrl * refresh_button = getRefreshBtn();
|
||||
if (!refresh_button->getVisible())
|
||||
{
|
||||
refresh_button->setVisible(true);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::draw()
|
||||
{
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
|
||||
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
|
||||
bool no_ongoing_connection = !(LLFlickrConnect::instance().isTransactionOngoing());
|
||||
mCancelButton->setEnabled(no_ongoing_connection);
|
||||
mTitleTextBox->setEnabled(no_ongoing_connection);
|
||||
mDescriptionTextBox->setEnabled(no_ongoing_connection);
|
||||
mTagsTextBox->setEnabled(no_ongoing_connection);
|
||||
mRatingComboBox->setEnabled(no_ongoing_connection);
|
||||
mResolutionComboBox->setEnabled(no_ongoing_connection);
|
||||
mFilterComboBox->setEnabled(no_ongoing_connection);
|
||||
mRefreshBtn->setEnabled(no_ongoing_connection);
|
||||
mBtnPreview->setEnabled(no_ongoing_connection);
|
||||
mLocationCheckbox->setEnabled(no_ongoing_connection);
|
||||
|
||||
// Reassign the preview floater if we have the focus and the preview exists
|
||||
if (hasFocus() && isPreviewVisible())
|
||||
{
|
||||
attachPreview();
|
||||
}
|
||||
|
||||
// Toggle the button state as appropriate
|
||||
bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
|
||||
mBtnPreview->setToggleState(preview_active);
|
||||
|
||||
// Display the preview if one is available
|
||||
if (previewp && previewp->getThumbnailImage())
|
||||
{
|
||||
const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
|
||||
const S32 thumbnail_w = previewp->getThumbnailWidth();
|
||||
const S32 thumbnail_h = previewp->getThumbnailHeight();
|
||||
|
||||
// calc preview offset within the preview rect
|
||||
const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
|
||||
const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
|
||||
|
||||
// calc preview offset within the floater rect
|
||||
// Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
|
||||
// This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
|
||||
// *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
|
||||
S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
|
||||
S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
|
||||
|
||||
mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
// Apply floater transparency to the texture unless the floater is focused.
|
||||
F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
|
||||
LLColor4 color = LLColor4::white;
|
||||
gl_draw_scaled_image(offset_x, offset_y,
|
||||
thumbnail_w, thumbnail_h,
|
||||
previewp->getThumbnailImage(), color % alpha);
|
||||
}
|
||||
|
||||
// Update the visibility of the working (computing preview) label
|
||||
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
|
||||
|
||||
// Enable Post if we have a preview to send and no on going connection being processed
|
||||
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()));
|
||||
|
||||
// Draw the rest of the panel on top of it
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
LLSnapshotLivePreview* LLFlickrPhotoPanel::getPreviewView()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
|
||||
return previewp;
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::onVisibilityChange(BOOL visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
if (mPreviewHandle.get())
|
||||
{
|
||||
LLSnapshotLivePreview* preview = getPreviewView();
|
||||
if(preview)
|
||||
{
|
||||
lldebugs << "opened, updating snapshot" << llendl;
|
||||
preview->updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLRect full_screen_rect = getRootView()->getRect();
|
||||
LLSnapshotLivePreview::Params p;
|
||||
p.rect(full_screen_rect);
|
||||
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
|
||||
mPreviewHandle = previewp->getHandle();
|
||||
|
||||
previewp->setContainer(this);
|
||||
previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
|
||||
previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG);
|
||||
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
|
||||
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
|
||||
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
|
||||
previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
|
||||
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::onClickNewSnapshot()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
if (previewp)
|
||||
{
|
||||
previewp->updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::onClickBigPreview()
|
||||
{
|
||||
// Toggle the preview
|
||||
if (isPreviewVisible())
|
||||
{
|
||||
LLFloaterReg::hideInstance("big_preview");
|
||||
}
|
||||
else
|
||||
{
|
||||
attachPreview();
|
||||
LLFloaterReg::showInstance("big_preview");
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFlickrPhotoPanel::isPreviewVisible()
|
||||
{
|
||||
return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::attachPreview()
|
||||
{
|
||||
if (mBigPreviewFloater)
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
mBigPreviewFloater->setPreview(previewp);
|
||||
mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::onSend()
|
||||
{
|
||||
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrPhotoPanel", boost::bind(&LLFlickrPhotoPanel::onFlickrConnectStateChange, this, _1));
|
||||
|
||||
// Connect to Flickr if necessary and then post
|
||||
if (LLFlickrConnect::instance().isConnected())
|
||||
{
|
||||
sendPhoto();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFlickrConnect::instance().checkConnectionToFlickr(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFlickrPhotoPanel::onFlickrConnectStateChange(const LLSD& data)
|
||||
{
|
||||
switch (data.get("enum").asInteger())
|
||||
{
|
||||
case LLFlickrConnect::FLICKR_CONNECTED:
|
||||
sendPhoto();
|
||||
break;
|
||||
|
||||
case LLFlickrConnect::FLICKR_POSTED:
|
||||
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrPhotoPanel");
|
||||
clearAndClose();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::sendPhoto()
|
||||
{
|
||||
// Get the title, description, and tags
|
||||
std::string title = mTitleTextBox->getValue().asString();
|
||||
std::string description = mDescriptionTextBox->getValue().asString();
|
||||
std::string tags = mTagsTextBox->getValue().asString();
|
||||
|
||||
// Add the location if required
|
||||
bool add_location = mLocationCheckbox->getValue().asBoolean();
|
||||
if (add_location)
|
||||
{
|
||||
// Get the SLURL for the location
|
||||
LLSLURL slurl;
|
||||
LLAgentUI::buildSLURL(slurl);
|
||||
std::string slurl_string = slurl.getSLURLString();
|
||||
|
||||
// Add query parameters so Google Analytics can track incoming clicks!
|
||||
slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
|
||||
|
||||
std::string photo_link_text = "Visit this location";// at [] in Second Life";
|
||||
std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
|
||||
if (!parcel_name.empty())
|
||||
{
|
||||
photo_link_text += " at " + parcel_name;
|
||||
}
|
||||
photo_link_text += " in Second Life";
|
||||
|
||||
slurl_string = "<a href=\"" + slurl_string + "\">" + photo_link_text + "</a>";
|
||||
|
||||
// Add it to the description (pretty crude, but we don't have a better option with photos)
|
||||
if (description.empty())
|
||||
description = slurl_string;
|
||||
else
|
||||
description = description + "\n\n" + slurl_string;
|
||||
|
||||
// Also add special "machine tags" with location metadata
|
||||
const LLVector3& agent_pos_region = gAgent.getPositionAgent();
|
||||
LLViewerRegion* region = gAgent.getRegion();
|
||||
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
||||
if (region && parcel)
|
||||
{
|
||||
S32 pos_x = S32(agent_pos_region.mV[VX]);
|
||||
S32 pos_y = S32(agent_pos_region.mV[VY]);
|
||||
S32 pos_z = S32(agent_pos_region.mV[VZ]);
|
||||
|
||||
std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName();
|
||||
std::string region_name = region->getName();
|
||||
|
||||
if (!region_name.empty())
|
||||
{
|
||||
tags += llformat(" \"%s:region=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), region_name.c_str());
|
||||
}
|
||||
if (!parcel_name.empty())
|
||||
{
|
||||
tags += llformat(" \"%s:parcel=%s\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), parcel_name.c_str());
|
||||
}
|
||||
tags += llformat(" \"%s:x=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_x);
|
||||
tags += llformat(" \"%s:y=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_y);
|
||||
tags += llformat(" \"%s:z=%d\"", FLICKR_MACHINE_TAGS_NAMESPACE.c_str(), pos_z);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the content rating
|
||||
int content_rating = mRatingComboBox->getValue().asInteger();
|
||||
|
||||
// Get the image
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
|
||||
// Post to Flickr
|
||||
LLFlickrConnect::instance().uploadPhoto(previewp->getFormattedImage(), title, description, tags, content_rating);
|
||||
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::clearAndClose()
|
||||
{
|
||||
mTitleTextBox->setValue("");
|
||||
mDescriptionTextBox->setValue("");
|
||||
|
||||
LLFloater* floater = getParentByType<LLFloater>();
|
||||
if (floater)
|
||||
{
|
||||
floater->closeFloater();
|
||||
if (mBigPreviewFloater)
|
||||
{
|
||||
mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::updateControls()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
|
||||
|
||||
// *TODO: Separate maximum size for Web images from postcards
|
||||
lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
|
||||
|
||||
updateResolution(FALSE);
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::updateResolution(BOOL do_update)
|
||||
{
|
||||
LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
|
||||
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
|
||||
|
||||
std::string sdstring = combobox->getSelectedValue();
|
||||
LLSD sdres;
|
||||
std::stringstream sstream(sdstring);
|
||||
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
|
||||
|
||||
S32 width = sdres[0];
|
||||
S32 height = sdres[1];
|
||||
|
||||
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
|
||||
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
|
||||
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
if (previewp && combobox->getCurrentIndex() >= 0)
|
||||
{
|
||||
S32 original_width = 0 , original_height = 0 ;
|
||||
previewp->getSize(original_width, original_height) ;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
// take resolution from current window size
|
||||
lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
|
||||
previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the resolution from the selected pre-canned drop-down choice
|
||||
lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
|
||||
previewp->setSize(width, height);
|
||||
}
|
||||
|
||||
checkAspectRatio(width);
|
||||
|
||||
previewp->getSize(width, height);
|
||||
if ((original_width != width) || (original_height != height))
|
||||
{
|
||||
previewp->setSize(width, height);
|
||||
if (do_update)
|
||||
{
|
||||
previewp->updateSnapshot(TRUE);
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
// Get the old filter, compare to the current one "filter_name" and set if changed
|
||||
std::string original_filter = previewp->getFilter();
|
||||
if (original_filter != filter_name)
|
||||
{
|
||||
previewp->setFilter(filter_name);
|
||||
if (do_update)
|
||||
{
|
||||
previewp->updateSnapshot(FALSE, TRUE);
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrPhotoPanel::checkAspectRatio(S32 index)
|
||||
{
|
||||
LLSnapshotLivePreview *previewp = getPreviewView() ;
|
||||
|
||||
BOOL keep_aspect = FALSE;
|
||||
|
||||
if (0 == index) // current window size
|
||||
{
|
||||
keep_aspect = TRUE;
|
||||
}
|
||||
else // predefined resolution
|
||||
{
|
||||
keep_aspect = FALSE;
|
||||
}
|
||||
|
||||
if (previewp)
|
||||
{
|
||||
previewp->mKeepAspectRatio = keep_aspect;
|
||||
}
|
||||
}
|
||||
|
||||
LLUICtrl* LLFlickrPhotoPanel::getRefreshBtn()
|
||||
{
|
||||
return mRefreshBtn;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//LLFlickrAccountPanel//////
|
||||
///////////////////////////
|
||||
|
||||
LLFlickrAccountPanel::LLFlickrAccountPanel() :
|
||||
mAccountCaptionLabel(NULL),
|
||||
mAccountNameLabel(NULL),
|
||||
mPanelButtons(NULL),
|
||||
mConnectButton(NULL),
|
||||
mDisconnectButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLFlickrAccountPanel::onConnect, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLFlickrAccountPanel::onDisconnect, this));
|
||||
|
||||
setVisibleCallback(boost::bind(&LLFlickrAccountPanel::onVisibilityChange, this, _2));
|
||||
}
|
||||
|
||||
BOOL LLFlickrAccountPanel::postBuild()
|
||||
{
|
||||
mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
|
||||
mAccountNameLabel = getChild<LLTextBox>("account_name_label");
|
||||
mPanelButtons = getChild<LLUICtrl>("panel_buttons");
|
||||
mConnectButton = getChild<LLUICtrl>("connect_btn");
|
||||
mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::draw()
|
||||
{
|
||||
LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState();
|
||||
|
||||
//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
|
||||
bool disconnecting = connection_state == LLFlickrConnect::FLICKR_DISCONNECTING;
|
||||
mDisconnectButton->setEnabled(!disconnecting);
|
||||
|
||||
//Disable the 'connect' button when a connection is in progress
|
||||
bool connecting = connection_state == LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS;
|
||||
mConnectButton->setEnabled(!connecting);
|
||||
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::onVisibilityChange(BOOL visible)
|
||||
{
|
||||
if(visible)
|
||||
{
|
||||
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
|
||||
LLEventPumps::instance().obtain("FlickrConnectState").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectStateChange, this, _1));
|
||||
|
||||
LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel");
|
||||
LLEventPumps::instance().obtain("FlickrConnectInfo").listen("LLFlickrAccountPanel", boost::bind(&LLFlickrAccountPanel::onFlickrConnectInfoChange, this));
|
||||
|
||||
//Connected
|
||||
if(LLFlickrConnect::instance().isConnected())
|
||||
{
|
||||
showConnectedLayout();
|
||||
}
|
||||
//Check if connected (show disconnected layout in meantime)
|
||||
else
|
||||
{
|
||||
showDisconnectedLayout();
|
||||
}
|
||||
if ((LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_NOT_CONNECTED) ||
|
||||
(LLFlickrConnect::instance().getConnectionState() == LLFlickrConnect::FLICKR_CONNECTION_FAILED))
|
||||
{
|
||||
LLFlickrConnect::instance().checkConnectionToFlickr();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLEventPumps::instance().obtain("FlickrConnectState").stopListening("LLFlickrAccountPanel");
|
||||
LLEventPumps::instance().obtain("FlickrConnectInfo").stopListening("LLFlickrAccountPanel");
|
||||
}
|
||||
}
|
||||
|
||||
bool LLFlickrAccountPanel::onFlickrConnectStateChange(const LLSD& data)
|
||||
{
|
||||
if(LLFlickrConnect::instance().isConnected())
|
||||
{
|
||||
//In process of disconnecting so leave the layout as is
|
||||
if(data.get("enum").asInteger() != LLFlickrConnect::FLICKR_DISCONNECTING)
|
||||
{
|
||||
showConnectedLayout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showDisconnectedLayout();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLFlickrAccountPanel::onFlickrConnectInfoChange()
|
||||
{
|
||||
LLSD info = LLFlickrConnect::instance().getInfo();
|
||||
std::string clickable_name;
|
||||
|
||||
//Strings of format [http://www.somewebsite.com Click Me] become clickable text
|
||||
if(info.has("link") && info.has("name"))
|
||||
{
|
||||
clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
|
||||
}
|
||||
|
||||
mAccountNameLabel->setText(clickable_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::showConnectButton()
|
||||
{
|
||||
if(!mConnectButton->getVisible())
|
||||
{
|
||||
mConnectButton->setVisible(TRUE);
|
||||
mDisconnectButton->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::hideConnectButton()
|
||||
{
|
||||
if(mConnectButton->getVisible())
|
||||
{
|
||||
mConnectButton->setVisible(FALSE);
|
||||
mDisconnectButton->setVisible(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::showDisconnectedLayout()
|
||||
{
|
||||
mAccountCaptionLabel->setText(getString("flickr_disconnected"));
|
||||
mAccountNameLabel->setText(std::string(""));
|
||||
showConnectButton();
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::showConnectedLayout()
|
||||
{
|
||||
LLFlickrConnect::instance().loadFlickrInfo();
|
||||
|
||||
mAccountCaptionLabel->setText(getString("flickr_connected"));
|
||||
hideConnectButton();
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::onConnect()
|
||||
{
|
||||
LLFlickrConnect::instance().checkConnectionToFlickr(true);
|
||||
|
||||
//Clear only the flickr browser cookies so that the flickr login screen appears
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com");
|
||||
}
|
||||
|
||||
void LLFlickrAccountPanel::onDisconnect()
|
||||
{
|
||||
LLFlickrConnect::instance().disconnectFromFlickr();
|
||||
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//LLFloaterFlickr///////
|
||||
////////////////////////
|
||||
|
||||
LLFloaterFlickr::LLFloaterFlickr(const LLSD& key) : LLFloater(key),
|
||||
mFlickrPhotoPanel(NULL),
|
||||
mStatusErrorText(NULL),
|
||||
mStatusLoadingText(NULL),
|
||||
mStatusLoadingIndicator(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterFlickr::onCancel, this));
|
||||
}
|
||||
|
||||
void LLFloaterFlickr::onClose(bool app_quitting)
|
||||
{
|
||||
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
if (big_preview_floater)
|
||||
{
|
||||
big_preview_floater->closeOnFloaterOwnerClosing(this);
|
||||
}
|
||||
LLFloater::onClose(app_quitting);
|
||||
}
|
||||
|
||||
void LLFloaterFlickr::onCancel()
|
||||
{
|
||||
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
if (big_preview_floater)
|
||||
{
|
||||
big_preview_floater->closeOnFloaterOwnerClosing(this);
|
||||
}
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
BOOL LLFloaterFlickr::postBuild()
|
||||
{
|
||||
// Keep tab of the Photo Panel
|
||||
mFlickrPhotoPanel = static_cast<LLFlickrPhotoPanel*>(getChild<LLUICtrl>("panel_flickr_photo"));
|
||||
// Connection status widgets
|
||||
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
|
||||
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
|
||||
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
|
||||
void LLFloaterFlickr::showPhotoPanel()
|
||||
{
|
||||
LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mFlickrPhotoPanel->getParent());
|
||||
if (!parent)
|
||||
{
|
||||
llwarns << "Cannot find panel container" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
parent->selectTabPanel(mFlickrPhotoPanel);
|
||||
}
|
||||
|
||||
void LLFloaterFlickr::draw()
|
||||
{
|
||||
if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
|
||||
{
|
||||
mStatusErrorText->setVisible(false);
|
||||
mStatusLoadingText->setVisible(false);
|
||||
mStatusLoadingIndicator->setVisible(false);
|
||||
LLFlickrConnect::EConnectionState connection_state = LLFlickrConnect::instance().getConnectionState();
|
||||
std::string status_text;
|
||||
|
||||
switch (connection_state)
|
||||
{
|
||||
case LLFlickrConnect::FLICKR_NOT_CONNECTED:
|
||||
// No status displayed when first opening the panel and no connection done
|
||||
case LLFlickrConnect::FLICKR_CONNECTED:
|
||||
// When successfully connected, no message is displayed
|
||||
case LLFlickrConnect::FLICKR_POSTED:
|
||||
// No success message to show since we actually close the floater after successful posting completion
|
||||
break;
|
||||
case LLFlickrConnect::FLICKR_CONNECTION_IN_PROGRESS:
|
||||
// Connection loading indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFlickrConnecting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLFlickrConnect::FLICKR_POSTING:
|
||||
// Posting indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFlickrPosting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLFlickrConnect::FLICKR_CONNECTION_FAILED:
|
||||
// Error connecting to the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFlickrErrorConnecting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
case LLFlickrConnect::FLICKR_POST_FAILED:
|
||||
// Error posting to the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFlickrErrorPosting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
case LLFlickrConnect::FLICKR_DISCONNECTING:
|
||||
// Disconnecting loading indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFlickrDisconnecting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLFlickrConnect::FLICKR_DISCONNECT_FAILED:
|
||||
// Error disconnecting from the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialFlickrErrorDisconnecting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* @file llfloaterflickr.h
|
||||
* @brief Header file for llfloaterflickr
|
||||
* @author cho@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_LLFLOATERFLICKR_H
|
||||
#define LL_LLFLOATERFLICKR_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llviewertexture.h"
|
||||
|
||||
class LLIconCtrl;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSnapshotLivePreview;
|
||||
class LLFloaterBigPreview;
|
||||
|
||||
class LLFlickrPhotoPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLFlickrPhotoPanel();
|
||||
~LLFlickrPhotoPanel();
|
||||
|
||||
BOOL postBuild();
|
||||
S32 notify(const LLSD& info);
|
||||
void draw();
|
||||
|
||||
LLSnapshotLivePreview* getPreviewView();
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
void onClickNewSnapshot();
|
||||
void onClickBigPreview();
|
||||
void onSend();
|
||||
bool onFlickrConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendPhoto();
|
||||
void clearAndClose();
|
||||
|
||||
void updateControls();
|
||||
void updateResolution(BOOL do_update);
|
||||
void checkAspectRatio(S32 index);
|
||||
LLUICtrl* getRefreshBtn();
|
||||
|
||||
private:
|
||||
bool isPreviewVisible();
|
||||
void attachPreview();
|
||||
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
|
||||
LLUICtrl * mSnapshotPanel;
|
||||
LLUICtrl * mResolutionComboBox;
|
||||
LLUICtrl * mFilterComboBox;
|
||||
LLUICtrl * mRefreshBtn;
|
||||
LLUICtrl * mWorkingLabel;
|
||||
LLUICtrl * mThumbnailPlaceholder;
|
||||
LLUICtrl * mTitleTextBox;
|
||||
LLUICtrl * mDescriptionTextBox;
|
||||
LLUICtrl * mLocationCheckbox;
|
||||
LLUICtrl * mTagsTextBox;
|
||||
LLUICtrl * mRatingComboBox;
|
||||
LLUICtrl * mPostButton;
|
||||
LLUICtrl * mCancelButton;
|
||||
LLButton * mBtnPreview;
|
||||
|
||||
LLFloaterBigPreview * mBigPreviewFloater;
|
||||
};
|
||||
|
||||
class LLFlickrAccountPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLFlickrAccountPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
private:
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
bool onFlickrConnectStateChange(const LLSD& data);
|
||||
bool onFlickrConnectInfoChange();
|
||||
void onConnect();
|
||||
void onUseAnotherAccount();
|
||||
void onDisconnect();
|
||||
|
||||
void showConnectButton();
|
||||
void hideConnectButton();
|
||||
void showDisconnectedLayout();
|
||||
void showConnectedLayout();
|
||||
|
||||
LLTextBox * mAccountCaptionLabel;
|
||||
LLTextBox * mAccountNameLabel;
|
||||
LLUICtrl * mPanelButtons;
|
||||
LLUICtrl * mConnectButton;
|
||||
LLUICtrl * mDisconnectButton;
|
||||
};
|
||||
|
||||
|
||||
class LLFloaterFlickr : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterFlickr(const LLSD& key);
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onClose(bool app_quitting);
|
||||
void onCancel();
|
||||
|
||||
void showPhotoPanel();
|
||||
|
||||
private:
|
||||
LLFlickrPhotoPanel* mFlickrPhotoPanel;
|
||||
LLTextBox* mStatusErrorText;
|
||||
LLTextBox* mStatusLoadingText;
|
||||
LLUICtrl* mStatusLoadingIndicator;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERFLICKR_H
|
||||
|
||||
|
|
@ -31,7 +31,10 @@
|
|||
#include "llagent.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloatersocial.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "llpostcard.h"
|
||||
|
|
@ -91,6 +94,7 @@ public:
|
|||
}
|
||||
static void onClickNewSnapshot(void* data);
|
||||
static void onClickAutoSnap(LLUICtrl *ctrl, void* data);
|
||||
static void onClickFilter(LLUICtrl *ctrl, void* data);
|
||||
//static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data);
|
||||
static void onClickMore(void* data) ;
|
||||
static void onClickUICheck(LLUICtrl *ctrl, void* data);
|
||||
|
|
@ -429,9 +433,8 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
|
|||
image_res_tb->setVisible(got_snap);
|
||||
if (got_snap)
|
||||
{
|
||||
LLPointer<LLImageRaw> img = previewp->getEncodedImage();
|
||||
image_res_tb->setTextArg("[WIDTH]", llformat("%d", img->getWidth()));
|
||||
image_res_tb->setTextArg("[HEIGHT]", llformat("%d", img->getHeight()));
|
||||
image_res_tb->setTextArg("[WIDTH]", llformat("%d", previewp->getEncodedImageWidth()));
|
||||
image_res_tb->setTextArg("[HEIGHT]", llformat("%d", previewp->getEncodedImageHeight()));
|
||||
}
|
||||
|
||||
floater->getChild<LLUICtrl>("file_size_label")->setTextArg("[SIZE]", got_snap ? bytes_string : floater->getString("unknown"));
|
||||
|
|
@ -464,8 +467,8 @@ void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (previewp)
|
||||
|
||||
if (previewp)
|
||||
{
|
||||
previewp->setSnapshotType(shot_type);
|
||||
previewp->setSnapshotFormat(shot_format);
|
||||
|
|
@ -558,6 +561,26 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data)
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSnapshot::Impl::onClickFilter(LLUICtrl *ctrl, void* data)
|
||||
{
|
||||
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
|
||||
if (view)
|
||||
{
|
||||
updateControls(view);
|
||||
LLSnapshotLivePreview* previewp = getPreviewView(view);
|
||||
if (previewp)
|
||||
{
|
||||
checkAutoSnapshot(previewp);
|
||||
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
|
||||
LLComboBox* filterbox = static_cast<LLComboBox *>(view->getChild<LLComboBox>("filters_combobox"));
|
||||
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
|
||||
previewp->setFilter(filter_name);
|
||||
previewp->updateSnapshot(FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterSnapshot::Impl::onClickMore(void* data)
|
||||
{
|
||||
BOOL visible = gSavedSettings.getBOOL("AdvanceSnapshot");
|
||||
|
|
@ -618,7 +641,7 @@ void LLFloaterSnapshot::Impl::applyKeepAspectCheck(LLFloaterSnapshot* view, BOOL
|
|||
|
||||
LL_DEBUGS() << "updating thumbnail" << LL_ENDL;
|
||||
previewp->setSize(w, h) ;
|
||||
previewp->updateSnapshot(FALSE, TRUE);
|
||||
previewp->updateSnapshot(TRUE);
|
||||
checkAutoSnapshot(previewp, TRUE);
|
||||
}
|
||||
}
|
||||
|
|
@ -853,7 +876,6 @@ void LLFloaterSnapshot::Impl::onImageQualityChange(LLFloaterSnapshot* view, S32
|
|||
{
|
||||
previewp->setSnapshotQuality(quality_val);
|
||||
}
|
||||
checkAutoSnapshot(previewp, TRUE);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -1052,7 +1074,26 @@ BOOL LLFloaterSnapshot::postBuild()
|
|||
|
||||
getChild<LLUICtrl>("auto_snapshot_check")->setValue(gSavedSettings.getBOOL("AutoSnapshot"));
|
||||
childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this);
|
||||
|
||||
|
||||
// Filters
|
||||
LLComboBox* filterbox = getChild<LLComboBox>("filters_combobox");
|
||||
if (gSavedSettings.getBOOL("SnapshotFiltersEnabled"))
|
||||
{
|
||||
// Update filter list if setting is on (experimental)
|
||||
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
|
||||
for (U32 i = 0; i < filter_list.size(); i++)
|
||||
{
|
||||
filterbox->add(filter_list[i]);
|
||||
}
|
||||
childSetCommitCallback("filters_combobox", Impl::onClickFilter, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide Filter UI if setting is off (default)
|
||||
getChild<LLUICtrl>("filter_list_label")->setVisible(FALSE);
|
||||
filterbox->setVisible(FALSE);
|
||||
}
|
||||
|
||||
LLWebProfile::setImageUploadResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSnapshotUploadFinished, _1));
|
||||
LLPostCard::setPostResultCallback(boost::bind(&LLFloaterSnapshot::Impl::onSendingPostcardFinished, _1));
|
||||
|
||||
|
|
@ -1082,6 +1123,7 @@ BOOL LLFloaterSnapshot::postBuild()
|
|||
getChild<LLComboBox>("local_format_combo")->selectNthItem(0);
|
||||
|
||||
impl.mPreviewHandle = previewp->getHandle();
|
||||
previewp->setContainer(this);
|
||||
impl.updateControls(this);
|
||||
impl.updateLayout(this);
|
||||
|
||||
|
|
@ -1246,6 +1288,32 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)
|
|||
impl.setStatus(Impl::STATUS_FINISHED, data["ok"].asBoolean(), data["msg"].asString());
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.has("snapshot-updating"))
|
||||
{
|
||||
// Disable the send/post/save buttons until snapshot is ready.
|
||||
impl.updateControls(this);
|
||||
// Force hiding the "Refresh to save" hint because we know we've just started refresh.
|
||||
impl.setNeedRefresh(this, false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.has("snapshot-updated"))
|
||||
{
|
||||
// Enable the send/post/save buttons.
|
||||
impl.updateControls(this);
|
||||
// We've just done refresh.
|
||||
impl.setNeedRefresh(this, false);
|
||||
|
||||
// The refresh button is initially hidden. We show it after the first update,
|
||||
// i.e. when preview appears.
|
||||
if (!mRefreshBtn->getVisible())
|
||||
{
|
||||
mRefreshBtn->setVisible(true);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1253,9 +1321,11 @@ S32 LLFloaterSnapshot::notify(const LLSD& info)
|
|||
void LLFloaterSnapshot::update()
|
||||
{
|
||||
LLFloaterSnapshot* inst = findInstance();
|
||||
LLFloaterSocial* floater_social = LLFloaterReg::findTypedInstance<LLFloaterSocial>("social");
|
||||
LLFloaterFacebook* floater_facebook = LLFloaterReg::findTypedInstance<LLFloaterFacebook>("facebook");
|
||||
LLFloaterFlickr* floater_flickr = LLFloaterReg::findTypedInstance<LLFloaterFlickr>("flickr");
|
||||
LLFloaterTwitter* floater_twitter = LLFloaterReg::findTypedInstance<LLFloaterTwitter>("twitter");
|
||||
|
||||
if (!inst && !floater_social)
|
||||
if (!inst && !floater_facebook && !floater_flickr && !floater_twitter)
|
||||
return;
|
||||
|
||||
BOOL changed = FALSE;
|
||||
|
|
@ -1328,43 +1398,6 @@ BOOL LLFloaterSnapshot::saveLocal()
|
|||
return previewp->saveLocal();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSnapshot::preUpdate()
|
||||
{
|
||||
// FIXME: duplicated code
|
||||
LLFloaterSnapshot* instance = findInstance();
|
||||
if (instance)
|
||||
{
|
||||
// Disable the send/post/save buttons until snapshot is ready.
|
||||
Impl::updateControls(instance);
|
||||
|
||||
// Force hiding the "Refresh to save" hint because we know we've just started refresh.
|
||||
Impl::setNeedRefresh(instance, false);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSnapshot::postUpdate()
|
||||
{
|
||||
// FIXME: duplicated code
|
||||
LLFloaterSnapshot* instance = findInstance();
|
||||
if (instance)
|
||||
{
|
||||
// Enable the send/post/save buttons.
|
||||
Impl::updateControls(instance);
|
||||
|
||||
// We've just done refresh.
|
||||
Impl::setNeedRefresh(instance, false);
|
||||
|
||||
// The refresh button is initially hidden. We show it after the first update,
|
||||
// i.e. when preview appears.
|
||||
if (!instance->mRefreshBtn->getVisible())
|
||||
{
|
||||
instance->mRefreshBtn->setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFloaterSnapshot::postSave()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ public:
|
|||
static LLFloaterSnapshot* findInstance();
|
||||
static void saveTexture();
|
||||
static BOOL saveLocal();
|
||||
static void preUpdate();
|
||||
static void postUpdate();
|
||||
static void postSave();
|
||||
static void postPanelSwitch();
|
||||
static LLPointer<LLImageFormatted> getImageData();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,827 @@
|
|||
/**
|
||||
* @file llfloatertwitter.cpp
|
||||
* @brief Implementation of llfloatertwitter
|
||||
* @author cho@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llfloatertwitter.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llagentui.h"
|
||||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "lltwitterconnect.h"
|
||||
#include "llfloaterbigpreview.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lliconctrl.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
#include "llresmgr.h" // LLLocale
|
||||
#include "llsdserialize.h"
|
||||
#include "llloadingindicator.h"
|
||||
#include "llplugincookiestore.h"
|
||||
#include "llslurl.h"
|
||||
#include "lltrans.h"
|
||||
#include "llsnapshotlivepreview.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llviewermedia.h"
|
||||
#include "lltabcontainer.h"
|
||||
#include "lltexteditor.h"
|
||||
|
||||
static LLPanelInjector<LLTwitterPhotoPanel> t_panel_photo("lltwitterphotopanel");
|
||||
static LLPanelInjector<LLTwitterAccountPanel> t_panel_account("lltwitteraccountpanel");
|
||||
|
||||
const S32 MAX_POSTCARD_DATASIZE = 1024 * 1024; // one megabyte
|
||||
const std::string DEFAULT_PHOTO_LOCATION_URL = "http://maps.secondlife.com/";
|
||||
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=twitter&utm_medium=photo&utm_campaign=slshare";
|
||||
const std::string DEFAULT_STATUS_TEXT = " #SecondLife";
|
||||
|
||||
///////////////////////////
|
||||
//LLTwitterPhotoPanel///////
|
||||
///////////////////////////
|
||||
|
||||
LLTwitterPhotoPanel::LLTwitterPhotoPanel() :
|
||||
mSnapshotPanel(NULL),
|
||||
mResolutionComboBox(NULL),
|
||||
mRefreshBtn(NULL),
|
||||
mBtnPreview(NULL),
|
||||
mWorkingLabel(NULL),
|
||||
mThumbnailPlaceholder(NULL),
|
||||
mStatusCounterLabel(NULL),
|
||||
mStatusTextBox(NULL),
|
||||
mLocationCheckbox(NULL),
|
||||
mPhotoCheckbox(NULL),
|
||||
mBigPreviewFloater(NULL),
|
||||
mPostButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.SendPhoto", boost::bind(&LLTwitterPhotoPanel::onSend, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.RefreshPhoto", boost::bind(&LLTwitterPhotoPanel::onClickNewSnapshot, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.BigPreview", boost::bind(&LLTwitterPhotoPanel::onClickBigPreview, this));
|
||||
}
|
||||
|
||||
LLTwitterPhotoPanel::~LLTwitterPhotoPanel()
|
||||
{
|
||||
if(mPreviewHandle.get())
|
||||
{
|
||||
mPreviewHandle.get()->die();
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLTwitterPhotoPanel::postBuild()
|
||||
{
|
||||
setVisibleCallback(boost::bind(&LLTwitterPhotoPanel::onVisibilityChange, this, _2));
|
||||
|
||||
mSnapshotPanel = getChild<LLUICtrl>("snapshot_panel");
|
||||
mResolutionComboBox = getChild<LLUICtrl>("resolution_combobox");
|
||||
mResolutionComboBox->setValue("[i800,i600]"); // hardcoded defaults ftw!
|
||||
mResolutionComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
|
||||
mFilterComboBox = getChild<LLUICtrl>("filters_combobox");
|
||||
mFilterComboBox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::updateResolution, this, TRUE));
|
||||
mRefreshBtn = getChild<LLUICtrl>("new_snapshot_btn");
|
||||
mBtnPreview = getChild<LLButton>("big_preview_btn");
|
||||
mWorkingLabel = getChild<LLUICtrl>("working_lbl");
|
||||
mThumbnailPlaceholder = getChild<LLUICtrl>("thumbnail_placeholder");
|
||||
mStatusCounterLabel = getChild<LLUICtrl>("status_counter_label");
|
||||
mStatusTextBox = getChild<LLUICtrl>("photo_status");
|
||||
mStatusTextBox->setValue(DEFAULT_STATUS_TEXT);
|
||||
mLocationCheckbox = getChild<LLUICtrl>("add_location_cb");
|
||||
mLocationCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddLocationToggled, this));
|
||||
mPhotoCheckbox = getChild<LLUICtrl>("add_photo_cb");
|
||||
mPhotoCheckbox->setCommitCallback(boost::bind(&LLTwitterPhotoPanel::onAddPhotoToggled, this));
|
||||
mPostButton = getChild<LLUICtrl>("post_photo_btn");
|
||||
mCancelButton = getChild<LLUICtrl>("cancel_photo_btn");
|
||||
mBigPreviewFloater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
|
||||
// Update filter list
|
||||
std::vector<std::string> filter_list = LLImageFiltersManager::getInstance()->getFiltersList();
|
||||
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
|
||||
for (U32 i = 0; i < filter_list.size(); i++)
|
||||
{
|
||||
filterbox->add(filter_list[i]);
|
||||
}
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
// virtual
|
||||
S32 LLTwitterPhotoPanel::notify(const LLSD& info)
|
||||
{
|
||||
if (info.has("snapshot-updating"))
|
||||
{
|
||||
// Disable the Post button and whatever else while the snapshot is not updated
|
||||
// updateControls();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (info.has("snapshot-updated"))
|
||||
{
|
||||
// Enable the send/post/save buttons.
|
||||
updateControls();
|
||||
|
||||
// The refresh button is initially hidden. We show it after the first update,
|
||||
// i.e. after snapshot is taken
|
||||
LLUICtrl * refresh_button = getRefreshBtn();
|
||||
if (!refresh_button->getVisible())
|
||||
{
|
||||
refresh_button->setVisible(true);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::draw()
|
||||
{
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
|
||||
// Enable interaction only if no transaction with the service is on-going (prevent duplicated posts)
|
||||
bool no_ongoing_connection = !(LLTwitterConnect::instance().isTransactionOngoing());
|
||||
bool photo_checked = mPhotoCheckbox->getValue().asBoolean();
|
||||
mCancelButton->setEnabled(no_ongoing_connection);
|
||||
mStatusTextBox->setEnabled(no_ongoing_connection);
|
||||
mResolutionComboBox->setEnabled(no_ongoing_connection && photo_checked);
|
||||
mFilterComboBox->setEnabled(no_ongoing_connection && photo_checked);
|
||||
mRefreshBtn->setEnabled(no_ongoing_connection && photo_checked);
|
||||
mBtnPreview->setEnabled(no_ongoing_connection);
|
||||
mLocationCheckbox->setEnabled(no_ongoing_connection);
|
||||
mPhotoCheckbox->setEnabled(no_ongoing_connection);
|
||||
|
||||
bool add_location = mLocationCheckbox->getValue().asBoolean();
|
||||
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
|
||||
updateStatusTextLength(false);
|
||||
|
||||
// Reassign the preview floater if we have the focus and the preview exists
|
||||
if (hasFocus() && isPreviewVisible())
|
||||
{
|
||||
attachPreview();
|
||||
}
|
||||
|
||||
// Toggle the button state as appropriate
|
||||
bool preview_active = (isPreviewVisible() && mBigPreviewFloater->isFloaterOwner(getParentByType<LLFloater>()));
|
||||
mBtnPreview->setToggleState(preview_active);
|
||||
|
||||
// Display the preview if one is available
|
||||
if (previewp && previewp->getThumbnailImage())
|
||||
{
|
||||
const LLRect& thumbnail_rect = mThumbnailPlaceholder->getRect();
|
||||
const S32 thumbnail_w = previewp->getThumbnailWidth();
|
||||
const S32 thumbnail_h = previewp->getThumbnailHeight();
|
||||
|
||||
// calc preview offset within the preview rect
|
||||
const S32 local_offset_x = (thumbnail_rect.getWidth() - thumbnail_w) / 2 ;
|
||||
const S32 local_offset_y = (thumbnail_rect.getHeight() - thumbnail_h) / 2 ;
|
||||
|
||||
// calc preview offset within the floater rect
|
||||
// Hack : To get the full offset, we need to take into account each and every offset of each widgets up to the floater.
|
||||
// This is almost as arbitrary as using a fixed offset so that's what we do here for the sake of simplicity.
|
||||
// *TODO : Get the offset looking through the hierarchy of widgets, should be done in postBuild() so to avoid traversing the hierarchy each time.
|
||||
S32 offset_x = thumbnail_rect.mLeft + local_offset_x - 1;
|
||||
S32 offset_y = thumbnail_rect.mBottom + local_offset_y - 39;
|
||||
|
||||
mSnapshotPanel->localPointToOtherView(offset_x, offset_y, &offset_x, &offset_y, getParentByType<LLFloater>());
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
// Apply floater transparency to the texture unless the floater is focused.
|
||||
F32 alpha = (add_photo ? (getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency()) : 0.5f);
|
||||
LLColor4 color = LLColor4::white;
|
||||
gl_draw_scaled_image(offset_x, offset_y,
|
||||
thumbnail_w, thumbnail_h,
|
||||
previewp->getThumbnailImage(), color % alpha);
|
||||
}
|
||||
|
||||
// Update the visibility of the working (computing preview) label
|
||||
mWorkingLabel->setVisible(!(previewp && previewp->getSnapshotUpToDate()));
|
||||
|
||||
// Enable Post if we have a preview to send and no on going connection being processed
|
||||
mPostButton->setEnabled(no_ongoing_connection && (previewp && previewp->getSnapshotUpToDate()) && (add_photo || add_location || !mStatusTextBox->getValue().asString().empty()));
|
||||
|
||||
// Draw the rest of the panel on top of it
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
LLSnapshotLivePreview* LLTwitterPhotoPanel::getPreviewView()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = (LLSnapshotLivePreview*)mPreviewHandle.get();
|
||||
return previewp;
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::onVisibilityChange(BOOL visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
if (mPreviewHandle.get())
|
||||
{
|
||||
LLSnapshotLivePreview* preview = getPreviewView();
|
||||
if(preview)
|
||||
{
|
||||
lldebugs << "opened, updating snapshot" << llendl;
|
||||
preview->updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLRect full_screen_rect = getRootView()->getRect();
|
||||
LLSnapshotLivePreview::Params p;
|
||||
p.rect(full_screen_rect);
|
||||
LLSnapshotLivePreview* previewp = new LLSnapshotLivePreview(p);
|
||||
mPreviewHandle = previewp->getHandle();
|
||||
|
||||
previewp->setContainer(this);
|
||||
previewp->setSnapshotType(previewp->SNAPSHOT_WEB);
|
||||
previewp->setSnapshotFormat(LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG);
|
||||
previewp->setThumbnailSubsampled(TRUE); // We want the preview to reflect the *saved* image
|
||||
previewp->setAllowRenderUI(FALSE); // We do not want the rendered UI in our snapshots
|
||||
previewp->setAllowFullScreenPreview(FALSE); // No full screen preview in SL Share mode
|
||||
previewp->setThumbnailPlaceholderRect(mThumbnailPlaceholder->getRect());
|
||||
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::onAddLocationToggled()
|
||||
{
|
||||
bool add_location = mLocationCheckbox->getValue().asBoolean();
|
||||
updateStatusTextLength(!add_location);
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::onAddPhotoToggled()
|
||||
{
|
||||
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
|
||||
updateStatusTextLength(!add_photo);
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::onClickNewSnapshot()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
if (previewp)
|
||||
{
|
||||
previewp->updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::onClickBigPreview()
|
||||
{
|
||||
// Toggle the preview
|
||||
if (isPreviewVisible())
|
||||
{
|
||||
LLFloaterReg::hideInstance("big_preview");
|
||||
}
|
||||
else
|
||||
{
|
||||
attachPreview();
|
||||
LLFloaterReg::showInstance("big_preview");
|
||||
}
|
||||
}
|
||||
|
||||
bool LLTwitterPhotoPanel::isPreviewVisible()
|
||||
{
|
||||
return (mBigPreviewFloater && mBigPreviewFloater->getVisible());
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::attachPreview()
|
||||
{
|
||||
if (mBigPreviewFloater)
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
mBigPreviewFloater->setPreview(previewp);
|
||||
mBigPreviewFloater->setFloaterOwner(getParentByType<LLFloater>());
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::onSend()
|
||||
{
|
||||
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel"); // just in case it is already listening
|
||||
LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterPhotoPanel", boost::bind(&LLTwitterPhotoPanel::onTwitterConnectStateChange, this, _1));
|
||||
|
||||
// Connect to Twitter if necessary and then post
|
||||
if (LLTwitterConnect::instance().isConnected())
|
||||
{
|
||||
sendPhoto();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLTwitterConnect::instance().checkConnectionToTwitter(true);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLTwitterPhotoPanel::onTwitterConnectStateChange(const LLSD& data)
|
||||
{
|
||||
switch (data.get("enum").asInteger())
|
||||
{
|
||||
case LLTwitterConnect::TWITTER_CONNECTED:
|
||||
sendPhoto();
|
||||
break;
|
||||
|
||||
case LLTwitterConnect::TWITTER_POSTED:
|
||||
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterPhotoPanel");
|
||||
clearAndClose();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::sendPhoto()
|
||||
{
|
||||
// Get the status text
|
||||
std::string status = mStatusTextBox->getValue().asString();
|
||||
|
||||
// Add the location if required
|
||||
bool add_location = mLocationCheckbox->getValue().asBoolean();
|
||||
if (add_location)
|
||||
{
|
||||
// Get the SLURL for the location
|
||||
LLSLURL slurl;
|
||||
LLAgentUI::buildSLURL(slurl);
|
||||
std::string slurl_string = slurl.getSLURLString();
|
||||
|
||||
// Use a valid http:// URL if the scheme is secondlife://
|
||||
LLURI slurl_uri(slurl_string);
|
||||
if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
|
||||
{
|
||||
slurl_string = DEFAULT_PHOTO_LOCATION_URL;
|
||||
}
|
||||
|
||||
// Add query parameters so Google Analytics can track incoming clicks!
|
||||
slurl_string += DEFAULT_PHOTO_QUERY_PARAMETERS;
|
||||
|
||||
// Add it to the status (pretty crude, but we don't have a better option with photos)
|
||||
if (status.empty())
|
||||
status = slurl_string;
|
||||
else
|
||||
status = status + " " + slurl_string;
|
||||
}
|
||||
|
||||
// Add the photo if required
|
||||
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
|
||||
if (add_photo)
|
||||
{
|
||||
// Get the image
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
|
||||
// Post to Twitter
|
||||
LLTwitterConnect::instance().uploadPhoto(previewp->getFormattedImage(), status);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just post the status to Twitter
|
||||
LLTwitterConnect::instance().updateStatus(status);
|
||||
}
|
||||
|
||||
updateControls();
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::clearAndClose()
|
||||
{
|
||||
mStatusTextBox->setValue(DEFAULT_STATUS_TEXT);
|
||||
|
||||
LLFloater* floater = getParentByType<LLFloater>();
|
||||
if (floater)
|
||||
{
|
||||
floater->closeFloater();
|
||||
if (mBigPreviewFloater)
|
||||
{
|
||||
mBigPreviewFloater->closeOnFloaterOwnerClosing(floater);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::updateStatusTextLength(BOOL restore_old_status_text)
|
||||
{
|
||||
bool add_location = mLocationCheckbox->getValue().asBoolean();
|
||||
bool add_photo = mPhotoCheckbox->getValue().asBoolean();
|
||||
|
||||
// Restrict the status text length to Twitter's character limit
|
||||
LLTextEditor* status_text_box = dynamic_cast<LLTextEditor*>(mStatusTextBox);
|
||||
if (status_text_box)
|
||||
{
|
||||
int max_status_length = 140 - (add_location ? 40 : 0) - (add_photo ? 40 : 0);
|
||||
status_text_box->setMaxTextLength(max_status_length);
|
||||
if (restore_old_status_text)
|
||||
{
|
||||
if (mOldStatusText.length() > status_text_box->getText().length() && status_text_box->getText() == mOldStatusText.substr(0, status_text_box->getText().length()))
|
||||
{
|
||||
status_text_box->setText(mOldStatusText);
|
||||
}
|
||||
if (mOldStatusText.length() <= max_status_length)
|
||||
{
|
||||
mOldStatusText = "";
|
||||
}
|
||||
}
|
||||
if (status_text_box->getText().length() > max_status_length)
|
||||
{
|
||||
if (mOldStatusText.length() < status_text_box->getText().length() || status_text_box->getText() != mOldStatusText.substr(0, status_text_box->getText().length()))
|
||||
{
|
||||
mOldStatusText = status_text_box->getText();
|
||||
}
|
||||
status_text_box->setText(mOldStatusText.substr(0, max_status_length));
|
||||
}
|
||||
|
||||
// Update the status character counter
|
||||
int characters_remaining = max_status_length - status_text_box->getText().length();
|
||||
mStatusCounterLabel->setValue(characters_remaining);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::updateControls()
|
||||
{
|
||||
LLSnapshotLivePreview* previewp = getPreviewView();
|
||||
BOOL got_snap = previewp && previewp->getSnapshotUpToDate();
|
||||
|
||||
// *TODO: Separate maximum size for Web images from postcards
|
||||
lldebugs << "Is snapshot up-to-date? " << got_snap << llendl;
|
||||
|
||||
updateResolution(FALSE);
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::updateResolution(BOOL do_update)
|
||||
{
|
||||
LLComboBox* combobox = static_cast<LLComboBox *>(mResolutionComboBox);
|
||||
LLComboBox* filterbox = static_cast<LLComboBox *>(mFilterComboBox);
|
||||
|
||||
std::string sdstring = combobox->getSelectedValue();
|
||||
LLSD sdres;
|
||||
std::stringstream sstream(sdstring);
|
||||
LLSDSerialize::fromNotation(sdres, sstream, sdstring.size());
|
||||
|
||||
S32 width = sdres[0];
|
||||
S32 height = sdres[1];
|
||||
|
||||
// Note : index 0 of the filter drop down is assumed to be "No filter" in whichever locale
|
||||
std::string filter_name = (filterbox->getCurrentIndex() ? filterbox->getSimple() : "");
|
||||
|
||||
LLSnapshotLivePreview * previewp = static_cast<LLSnapshotLivePreview *>(mPreviewHandle.get());
|
||||
if (previewp && combobox->getCurrentIndex() >= 0)
|
||||
{
|
||||
S32 original_width = 0 , original_height = 0 ;
|
||||
previewp->getSize(original_width, original_height) ;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
// take resolution from current window size
|
||||
lldebugs << "Setting preview res from window: " << gViewerWindow->getWindowWidthRaw() << "x" << gViewerWindow->getWindowHeightRaw() << llendl;
|
||||
previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw());
|
||||
}
|
||||
else
|
||||
{
|
||||
// use the resolution from the selected pre-canned drop-down choice
|
||||
lldebugs << "Setting preview res selected from combo: " << width << "x" << height << llendl;
|
||||
previewp->setSize(width, height);
|
||||
}
|
||||
|
||||
checkAspectRatio(width);
|
||||
|
||||
previewp->getSize(width, height);
|
||||
|
||||
if (original_width != width || original_height != height)
|
||||
{
|
||||
previewp->setSize(width, height);
|
||||
if (do_update)
|
||||
{
|
||||
previewp->updateSnapshot(TRUE);
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
// Get the old filter, compare to the current one "filter_name" and set if changed
|
||||
std::string original_filter = previewp->getFilter();
|
||||
if (original_filter != filter_name)
|
||||
{
|
||||
previewp->setFilter(filter_name);
|
||||
if (do_update)
|
||||
{
|
||||
previewp->updateSnapshot(FALSE, TRUE);
|
||||
updateControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterPhotoPanel::checkAspectRatio(S32 index)
|
||||
{
|
||||
LLSnapshotLivePreview *previewp = getPreviewView() ;
|
||||
|
||||
BOOL keep_aspect = FALSE;
|
||||
|
||||
if (0 == index) // current window size
|
||||
{
|
||||
keep_aspect = TRUE;
|
||||
}
|
||||
else // predefined resolution
|
||||
{
|
||||
keep_aspect = FALSE;
|
||||
}
|
||||
|
||||
if (previewp)
|
||||
{
|
||||
previewp->mKeepAspectRatio = keep_aspect;
|
||||
}
|
||||
}
|
||||
|
||||
LLUICtrl* LLTwitterPhotoPanel::getRefreshBtn()
|
||||
{
|
||||
return mRefreshBtn;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
//LLTwitterAccountPanel//////
|
||||
///////////////////////////
|
||||
|
||||
LLTwitterAccountPanel::LLTwitterAccountPanel() :
|
||||
mAccountCaptionLabel(NULL),
|
||||
mAccountNameLabel(NULL),
|
||||
mPanelButtons(NULL),
|
||||
mConnectButton(NULL),
|
||||
mDisconnectButton(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Connect", boost::bind(&LLTwitterAccountPanel::onConnect, this));
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Disconnect", boost::bind(&LLTwitterAccountPanel::onDisconnect, this));
|
||||
|
||||
setVisibleCallback(boost::bind(&LLTwitterAccountPanel::onVisibilityChange, this, _2));
|
||||
}
|
||||
|
||||
BOOL LLTwitterAccountPanel::postBuild()
|
||||
{
|
||||
mAccountCaptionLabel = getChild<LLTextBox>("account_caption_label");
|
||||
mAccountNameLabel = getChild<LLTextBox>("account_name_label");
|
||||
mPanelButtons = getChild<LLUICtrl>("panel_buttons");
|
||||
mConnectButton = getChild<LLUICtrl>("connect_btn");
|
||||
mDisconnectButton = getChild<LLUICtrl>("disconnect_btn");
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::draw()
|
||||
{
|
||||
LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState();
|
||||
|
||||
//Disable the 'disconnect' button and the 'use another account' button when disconnecting in progress
|
||||
bool disconnecting = connection_state == LLTwitterConnect::TWITTER_DISCONNECTING;
|
||||
mDisconnectButton->setEnabled(!disconnecting);
|
||||
|
||||
//Disable the 'connect' button when a connection is in progress
|
||||
bool connecting = connection_state == LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS;
|
||||
mConnectButton->setEnabled(!connecting);
|
||||
|
||||
LLPanel::draw();
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::onVisibilityChange(BOOL visible)
|
||||
{
|
||||
if(visible)
|
||||
{
|
||||
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
|
||||
LLEventPumps::instance().obtain("TwitterConnectState").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectStateChange, this, _1));
|
||||
|
||||
LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel");
|
||||
LLEventPumps::instance().obtain("TwitterConnectInfo").listen("LLTwitterAccountPanel", boost::bind(&LLTwitterAccountPanel::onTwitterConnectInfoChange, this));
|
||||
|
||||
//Connected
|
||||
if(LLTwitterConnect::instance().isConnected())
|
||||
{
|
||||
showConnectedLayout();
|
||||
}
|
||||
//Check if connected (show disconnected layout in meantime)
|
||||
else
|
||||
{
|
||||
showDisconnectedLayout();
|
||||
}
|
||||
if ((LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_NOT_CONNECTED) ||
|
||||
(LLTwitterConnect::instance().getConnectionState() == LLTwitterConnect::TWITTER_CONNECTION_FAILED))
|
||||
{
|
||||
LLTwitterConnect::instance().checkConnectionToTwitter();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LLEventPumps::instance().obtain("TwitterConnectState").stopListening("LLTwitterAccountPanel");
|
||||
LLEventPumps::instance().obtain("TwitterConnectInfo").stopListening("LLTwitterAccountPanel");
|
||||
}
|
||||
}
|
||||
|
||||
bool LLTwitterAccountPanel::onTwitterConnectStateChange(const LLSD& data)
|
||||
{
|
||||
if(LLTwitterConnect::instance().isConnected())
|
||||
{
|
||||
//In process of disconnecting so leave the layout as is
|
||||
if(data.get("enum").asInteger() != LLTwitterConnect::TWITTER_DISCONNECTING)
|
||||
{
|
||||
showConnectedLayout();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
showDisconnectedLayout();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLTwitterAccountPanel::onTwitterConnectInfoChange()
|
||||
{
|
||||
LLSD info = LLTwitterConnect::instance().getInfo();
|
||||
std::string clickable_name;
|
||||
|
||||
//Strings of format [http://www.somewebsite.com Click Me] become clickable text
|
||||
if(info.has("link") && info.has("name"))
|
||||
{
|
||||
clickable_name = "[" + info["link"].asString() + " " + info["name"].asString() + "]";
|
||||
}
|
||||
|
||||
mAccountNameLabel->setText(clickable_name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::showConnectButton()
|
||||
{
|
||||
if(!mConnectButton->getVisible())
|
||||
{
|
||||
mConnectButton->setVisible(TRUE);
|
||||
mDisconnectButton->setVisible(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::hideConnectButton()
|
||||
{
|
||||
if(mConnectButton->getVisible())
|
||||
{
|
||||
mConnectButton->setVisible(FALSE);
|
||||
mDisconnectButton->setVisible(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::showDisconnectedLayout()
|
||||
{
|
||||
mAccountCaptionLabel->setText(getString("twitter_disconnected"));
|
||||
mAccountNameLabel->setText(std::string(""));
|
||||
showConnectButton();
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::showConnectedLayout()
|
||||
{
|
||||
LLTwitterConnect::instance().loadTwitterInfo();
|
||||
|
||||
mAccountCaptionLabel->setText(getString("twitter_connected"));
|
||||
hideConnectButton();
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::onConnect()
|
||||
{
|
||||
LLTwitterConnect::instance().checkConnectionToTwitter(true);
|
||||
|
||||
//Clear only the twitter browser cookies so that the twitter login screen appears
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com");
|
||||
}
|
||||
|
||||
void LLTwitterAccountPanel::onDisconnect()
|
||||
{
|
||||
LLTwitterConnect::instance().disconnectFromTwitter();
|
||||
|
||||
LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com");
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
//LLFloaterTwitter///////
|
||||
////////////////////////
|
||||
|
||||
LLFloaterTwitter::LLFloaterTwitter(const LLSD& key) : LLFloater(key),
|
||||
mTwitterPhotoPanel(NULL),
|
||||
mStatusErrorText(NULL),
|
||||
mStatusLoadingText(NULL),
|
||||
mStatusLoadingIndicator(NULL)
|
||||
{
|
||||
mCommitCallbackRegistrar.add("SocialSharing.Cancel", boost::bind(&LLFloaterTwitter::onCancel, this));
|
||||
}
|
||||
|
||||
void LLFloaterTwitter::onClose(bool app_quitting)
|
||||
{
|
||||
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
if (big_preview_floater)
|
||||
{
|
||||
big_preview_floater->closeOnFloaterOwnerClosing(this);
|
||||
}
|
||||
LLFloater::onClose(app_quitting);
|
||||
}
|
||||
|
||||
void LLFloaterTwitter::onCancel()
|
||||
{
|
||||
LLFloaterBigPreview* big_preview_floater = dynamic_cast<LLFloaterBigPreview*>(LLFloaterReg::getInstance("big_preview"));
|
||||
if (big_preview_floater)
|
||||
{
|
||||
big_preview_floater->closeOnFloaterOwnerClosing(this);
|
||||
}
|
||||
closeFloater();
|
||||
}
|
||||
|
||||
BOOL LLFloaterTwitter::postBuild()
|
||||
{
|
||||
// Keep tab of the Photo Panel
|
||||
mTwitterPhotoPanel = static_cast<LLTwitterPhotoPanel*>(getChild<LLUICtrl>("panel_twitter_photo"));
|
||||
// Connection status widgets
|
||||
mStatusErrorText = getChild<LLTextBox>("connection_error_text");
|
||||
mStatusLoadingText = getChild<LLTextBox>("connection_loading_text");
|
||||
mStatusLoadingIndicator = getChild<LLUICtrl>("connection_loading_indicator");
|
||||
return LLFloater::postBuild();
|
||||
}
|
||||
|
||||
void LLFloaterTwitter::showPhotoPanel()
|
||||
{
|
||||
LLTabContainer* parent = dynamic_cast<LLTabContainer*>(mTwitterPhotoPanel->getParent());
|
||||
if (!parent)
|
||||
{
|
||||
llwarns << "Cannot find panel container" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
parent->selectTabPanel(mTwitterPhotoPanel);
|
||||
}
|
||||
|
||||
void LLFloaterTwitter::draw()
|
||||
{
|
||||
if (mStatusErrorText && mStatusLoadingText && mStatusLoadingIndicator)
|
||||
{
|
||||
mStatusErrorText->setVisible(false);
|
||||
mStatusLoadingText->setVisible(false);
|
||||
mStatusLoadingIndicator->setVisible(false);
|
||||
LLTwitterConnect::EConnectionState connection_state = LLTwitterConnect::instance().getConnectionState();
|
||||
std::string status_text;
|
||||
|
||||
switch (connection_state)
|
||||
{
|
||||
case LLTwitterConnect::TWITTER_NOT_CONNECTED:
|
||||
// No status displayed when first opening the panel and no connection done
|
||||
case LLTwitterConnect::TWITTER_CONNECTED:
|
||||
// When successfully connected, no message is displayed
|
||||
case LLTwitterConnect::TWITTER_POSTED:
|
||||
// No success message to show since we actually close the floater after successful posting completion
|
||||
break;
|
||||
case LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS:
|
||||
// Connection loading indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialTwitterConnecting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLTwitterConnect::TWITTER_POSTING:
|
||||
// Posting indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialTwitterPosting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLTwitterConnect::TWITTER_CONNECTION_FAILED:
|
||||
// Error connecting to the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialTwitterErrorConnecting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
case LLTwitterConnect::TWITTER_POST_FAILED:
|
||||
// Error posting to the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialTwitterErrorPosting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
case LLTwitterConnect::TWITTER_DISCONNECTING:
|
||||
// Disconnecting loading indicator
|
||||
mStatusLoadingText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialTwitterDisconnecting");
|
||||
mStatusLoadingText->setValue(status_text);
|
||||
mStatusLoadingIndicator->setVisible(true);
|
||||
break;
|
||||
case LLTwitterConnect::TWITTER_DISCONNECT_FAILED:
|
||||
// Error disconnecting from the service
|
||||
mStatusErrorText->setVisible(true);
|
||||
status_text = LLTrans::getString("SocialTwitterErrorDisconnecting");
|
||||
mStatusErrorText->setValue(status_text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LLFloater::draw();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* @file llfloatertwitter.h
|
||||
* @brief Header file for llfloatertwitter
|
||||
* @author cho@lindenlab.com
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_LLFLOATERTWITTER_H
|
||||
#define LL_LLFLOATERTWITTER_H
|
||||
|
||||
#include "llfloater.h"
|
||||
#include "lltextbox.h"
|
||||
#include "llviewertexture.h"
|
||||
|
||||
class LLIconCtrl;
|
||||
class LLCheckBoxCtrl;
|
||||
class LLSnapshotLivePreview;
|
||||
class LLFloaterBigPreview;
|
||||
|
||||
class LLTwitterPhotoPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLTwitterPhotoPanel();
|
||||
~LLTwitterPhotoPanel();
|
||||
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
LLSnapshotLivePreview* getPreviewView();
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
void onAddLocationToggled();
|
||||
void onAddPhotoToggled();
|
||||
void onClickBigPreview();
|
||||
void onClickNewSnapshot();
|
||||
void onSend();
|
||||
S32 notify(const LLSD& info);
|
||||
bool onTwitterConnectStateChange(const LLSD& data);
|
||||
|
||||
void sendPhoto();
|
||||
void clearAndClose();
|
||||
|
||||
void updateStatusTextLength(BOOL restore_old_status_text);
|
||||
void updateControls();
|
||||
void updateResolution(BOOL do_update);
|
||||
void checkAspectRatio(S32 index);
|
||||
LLUICtrl* getRefreshBtn();
|
||||
|
||||
private:
|
||||
bool isPreviewVisible();
|
||||
void attachPreview();
|
||||
|
||||
LLHandle<LLView> mPreviewHandle;
|
||||
|
||||
LLUICtrl * mSnapshotPanel;
|
||||
LLUICtrl * mResolutionComboBox;
|
||||
LLUICtrl * mFilterComboBox;
|
||||
LLUICtrl * mRefreshBtn;
|
||||
LLUICtrl * mWorkingLabel;
|
||||
LLUICtrl * mThumbnailPlaceholder;
|
||||
LLUICtrl * mStatusCounterLabel;
|
||||
LLUICtrl * mStatusTextBox;
|
||||
LLUICtrl * mLocationCheckbox;
|
||||
LLUICtrl * mPhotoCheckbox;
|
||||
LLUICtrl * mPostButton;
|
||||
LLUICtrl * mCancelButton;
|
||||
LLButton * mBtnPreview;
|
||||
|
||||
LLFloaterBigPreview * mBigPreviewFloater;
|
||||
|
||||
std::string mOldStatusText;
|
||||
};
|
||||
|
||||
class LLTwitterAccountPanel : public LLPanel
|
||||
{
|
||||
public:
|
||||
LLTwitterAccountPanel();
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
|
||||
private:
|
||||
void onVisibilityChange(BOOL new_visibility);
|
||||
bool onTwitterConnectStateChange(const LLSD& data);
|
||||
bool onTwitterConnectInfoChange();
|
||||
void onConnect();
|
||||
void onUseAnotherAccount();
|
||||
void onDisconnect();
|
||||
|
||||
void showConnectButton();
|
||||
void hideConnectButton();
|
||||
void showDisconnectedLayout();
|
||||
void showConnectedLayout();
|
||||
|
||||
LLTextBox * mAccountCaptionLabel;
|
||||
LLTextBox * mAccountNameLabel;
|
||||
LLUICtrl * mPanelButtons;
|
||||
LLUICtrl * mConnectButton;
|
||||
LLUICtrl * mDisconnectButton;
|
||||
};
|
||||
|
||||
|
||||
class LLFloaterTwitter : public LLFloater
|
||||
{
|
||||
public:
|
||||
LLFloaterTwitter(const LLSD& key);
|
||||
BOOL postBuild();
|
||||
void draw();
|
||||
void onClose(bool app_quitting);
|
||||
void onCancel();
|
||||
|
||||
void showPhotoPanel();
|
||||
|
||||
private:
|
||||
LLTwitterPhotoPanel* mTwitterPhotoPanel;
|
||||
LLTextBox* mStatusErrorText;
|
||||
LLTextBox* mStatusLoadingText;
|
||||
LLUICtrl* mStatusLoadingIndicator;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERTWITTER_H
|
||||
|
||||
|
|
@ -1050,12 +1050,11 @@ void LLFloaterUIPreview::onClickEditFloater()
|
|||
// Respond to button click to browse for an executable with which to edit XML files
|
||||
void LLFloaterUIPreview::onClickBrowseForEditor()
|
||||
{
|
||||
// create load dialog box
|
||||
LLFilePicker::ELoadFilter type = (LLFilePicker::ELoadFilter)((intptr_t)((void*)LLFilePicker::FFLOAD_ALL)); // nothing for *.exe so just use all
|
||||
// Let the user choose an executable through the file picker dialog box
|
||||
LLFilePicker& picker = LLFilePicker::instance();
|
||||
if (!picker.getOpenFile(type)) // user cancelled -- do nothing
|
||||
if (!picker.getOpenFile(LLFilePicker::FFLOAD_EXE))
|
||||
{
|
||||
return;
|
||||
return; // user cancelled -- do nothing
|
||||
}
|
||||
|
||||
// put the selected path into text field
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
#include "llfloaterreg.h"
|
||||
#include "llhttpconstants.h"
|
||||
#include "llfacebookconnect.h"
|
||||
#include "llflickrconnect.h"
|
||||
#include "lltwitterconnect.h"
|
||||
#include "lllayoutstack.h"
|
||||
#include "llpluginclassmedia.h"
|
||||
#include "llprogressbar.h"
|
||||
|
|
@ -52,7 +54,8 @@ LLFloaterWebContent::_Params::_Params()
|
|||
allow_back_forward_navigation("allow_back_forward_navigation", true),
|
||||
preferred_media_size("preferred_media_size"),
|
||||
trusted_content("trusted_content", false),
|
||||
show_page_title("show_page_title", true)
|
||||
show_page_title("show_page_title", true),
|
||||
clean_browser("clean_browser", false)
|
||||
{}
|
||||
|
||||
LLFloaterWebContent::LLFloaterWebContent( const Params& params )
|
||||
|
|
@ -249,7 +252,7 @@ void LLFloaterWebContent::open_media(const Params& p)
|
|||
LLViewerMedia::proxyWindowOpened(p.target(), p.id());
|
||||
mWebBrowser->setHomePageUrl(p.url, HTTP_CONTENT_TEXT_HTML);
|
||||
mWebBrowser->setTarget(p.target);
|
||||
mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML);
|
||||
mWebBrowser->navigateTo(p.url, HTTP_CONTENT_TEXT_HTML, p.clean_browser);
|
||||
|
||||
set_current_url(p.url);
|
||||
|
||||
|
|
@ -260,11 +263,6 @@ void LLFloaterWebContent::open_media(const Params& p)
|
|||
getChildView("address")->setEnabled(address_entry_enabled);
|
||||
getChildView("popexternal")->setEnabled(address_entry_enabled);
|
||||
|
||||
if (!address_entry_enabled)
|
||||
{
|
||||
mWebBrowser->setFocus(TRUE);
|
||||
}
|
||||
|
||||
if (!p.show_chrome)
|
||||
{
|
||||
setResizeLimits(100, 100);
|
||||
|
|
@ -318,7 +316,24 @@ void LLFloaterWebContent::onClose(bool app_quitting)
|
|||
LLFacebookConnect::instance().setConnectionState(LLFacebookConnect::FB_CONNECTION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
// Same with Flickr
|
||||
LLFloater* flickr_web = LLFloaterReg::getInstance("flickr_web");
|
||||
if (flickr_web == this)
|
||||
{
|
||||
if (!LLFlickrConnect::instance().isConnected())
|
||||
{
|
||||
LLFlickrConnect::instance().setConnectionState(LLFlickrConnect::FLICKR_CONNECTION_FAILED);
|
||||
}
|
||||
}
|
||||
// And Twitter
|
||||
LLFloater* twitter_web = LLFloaterReg::getInstance("twitter_web");
|
||||
if (twitter_web == this)
|
||||
{
|
||||
if (!LLTwitterConnect::instance().isConnected())
|
||||
{
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
|
||||
}
|
||||
}
|
||||
LLViewerMedia::proxyWindowClosed(mUUID);
|
||||
destroy();
|
||||
}
|
||||
|
|
@ -457,9 +472,6 @@ void LLFloaterWebContent::set_current_url(const std::string& url)
|
|||
mAddressCombo->remove(mCurrentURL);
|
||||
mAddressCombo->add(mDisplayURL);
|
||||
mAddressCombo->selectByValue(mDisplayURL);
|
||||
|
||||
// Set the focus back to the web page. When setting the url, there's no point to leave the focus anywhere else.
|
||||
mWebBrowser->setFocus(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@ public:
|
|||
allow_address_entry,
|
||||
allow_back_forward_navigation,
|
||||
trusted_content,
|
||||
show_page_title;
|
||||
show_page_title,
|
||||
clean_browser;
|
||||
Optional<LLRect> preferred_media_size;
|
||||
|
||||
_Params();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* @file llimagefiltersmanager.cpp
|
||||
* @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llimagefiltersmanager.h"
|
||||
|
||||
#include "lldiriterator.h"
|
||||
#include "lltrans.h"
|
||||
|
||||
std::string get_sys_dir()
|
||||
{
|
||||
return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "filters", "");
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// LLImageFiltersManager
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLImageFiltersManager::LLImageFiltersManager()
|
||||
{
|
||||
}
|
||||
|
||||
LLImageFiltersManager::~LLImageFiltersManager()
|
||||
{
|
||||
}
|
||||
|
||||
// virtual static
|
||||
void LLImageFiltersManager::initSingleton()
|
||||
{
|
||||
loadAllFilters();
|
||||
}
|
||||
|
||||
void LLImageFiltersManager::loadAllFilters()
|
||||
{
|
||||
// Load system (coming out of the box) filters
|
||||
loadFiltersFromDir(get_sys_dir());
|
||||
}
|
||||
|
||||
void LLImageFiltersManager::loadFiltersFromDir(const std::string& dir)
|
||||
{
|
||||
mFiltersList.clear();
|
||||
|
||||
LLDirIterator dir_iter(dir, "*.xml");
|
||||
while (1)
|
||||
{
|
||||
std::string file_name;
|
||||
if (!dir_iter.next(file_name))
|
||||
{
|
||||
break; // no more files
|
||||
}
|
||||
|
||||
// Get the ".xml" out of the file name to get the filter name. That's the one known in strings.xml
|
||||
std::string filter_name_untranslated = file_name.substr(0,file_name.length()-4);
|
||||
|
||||
// Get the localized name for the filter
|
||||
std::string filter_name_translated;
|
||||
bool translated = LLTrans::findString(filter_name_translated, filter_name_untranslated);
|
||||
std::string filter_name = (translated ? filter_name_translated: filter_name_untranslated);
|
||||
|
||||
// Store the filter in the list with its associated file name
|
||||
mFiltersList[filter_name] = file_name;
|
||||
}
|
||||
}
|
||||
|
||||
// Note : That method is a bit heavy handed but the list of filters is always small (10 or so)
|
||||
// and that method is typically called only once when building UI widgets.
|
||||
const std::vector<std::string> LLImageFiltersManager::getFiltersList() const
|
||||
{
|
||||
std::vector<std::string> filter_list;
|
||||
for (std::map<std::string,std::string>::const_iterator it = mFiltersList.begin(); it != mFiltersList.end(); ++it)
|
||||
{
|
||||
filter_list.push_back(it->first);
|
||||
}
|
||||
return filter_list;
|
||||
}
|
||||
|
||||
std::string LLImageFiltersManager::getFilterPath(const std::string& filter_name)
|
||||
{
|
||||
std::string path = "";
|
||||
std::map<std::string,std::string>::const_iterator it = mFiltersList.find(filter_name);
|
||||
if (it != mFiltersList.end())
|
||||
{
|
||||
// Get the file name for that filter and build the complete path
|
||||
std::string file = it->second;
|
||||
std::string dir = get_sys_dir();
|
||||
path = gDirUtilp->add(dir, file);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* @file llimagefiltersmanager.h
|
||||
* @brief Load image filters list and retrieve their path. Mostly used for Flickr UI at the moment.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2014, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLIMAGEFILTERSMANAGER_H
|
||||
#define LL_LLIMAGEFILTERSMANAGER_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
|
||||
//============================================================================
|
||||
// LLImageFiltersManager class
|
||||
|
||||
class LLImageFiltersManager : public LLSingleton<LLImageFiltersManager>
|
||||
{
|
||||
LOG_CLASS(LLImageFiltersManager);
|
||||
public:
|
||||
const std::vector<std::string> getFiltersList() const;
|
||||
std::string getFilterPath(const std::string& filter_name);
|
||||
|
||||
private:
|
||||
void loadAllFilters();
|
||||
void loadFiltersFromDir(const std::string& dir);
|
||||
|
||||
friend class LLSingleton<LLImageFiltersManager>;
|
||||
/*virtual*/ void initSingleton();
|
||||
LLImageFiltersManager();
|
||||
~LLImageFiltersManager();
|
||||
|
||||
// List of filters : first is the user friendly localized name, second is the xml file name
|
||||
std::map<std::string,std::string> mFiltersList;
|
||||
};
|
||||
|
||||
#endif // LL_LLIMAGEFILTERSMANAGER_H
|
||||
|
|
@ -561,7 +561,7 @@ void LLMediaCtrl::clearCache()
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
|
||||
void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser)
|
||||
{
|
||||
// <AW>
|
||||
// don't browse to slurls like "secondlife://" or "hop://"
|
||||
|
|
@ -580,7 +580,7 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type)
|
|||
{
|
||||
mCurrentNavUrl = url_in;
|
||||
mMediaSource->setSize(mTextureWidth, mTextureHeight);
|
||||
mMediaSource->navigateTo(url_in, mime_type, mime_type.empty());
|
||||
mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ public:
|
|||
virtual BOOL handleToolTip(S32 x, S32 y, MASK mask);
|
||||
|
||||
// navigation
|
||||
void navigateTo( std::string url_in, std::string mime_type = "");
|
||||
void navigateTo( std::string url_in, std::string mime_type = "", bool clean_browser = false);
|
||||
void navigateBack();
|
||||
void navigateHome();
|
||||
void navigateForward();
|
||||
|
|
|
|||
|
|
@ -521,7 +521,7 @@ public:
|
|||
|
||||
LLPanelPeople::LLPanelPeople()
|
||||
: LLPanel(),
|
||||
mTryToConnectToFbc(true),
|
||||
mTryToConnectToFacebook(true),
|
||||
mTabContainer(NULL),
|
||||
mOnlineFriendList(NULL),
|
||||
mAllFriendList(NULL),
|
||||
|
|
@ -963,10 +963,10 @@ void LLPanelPeople::updateFacebookList(bool visible)
|
|||
{
|
||||
LLFacebookConnect::instance().loadFacebookFriends();
|
||||
}
|
||||
else if(mTryToConnectToFbc)
|
||||
else if(mTryToConnectToFacebook)
|
||||
{
|
||||
LLFacebookConnect::instance().checkConnectionToFacebook();
|
||||
mTryToConnectToFbc = false;
|
||||
mTryToConnectToFacebook = false;
|
||||
}
|
||||
|
||||
updateSuggestedFriendList();
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public:
|
|||
// when voice is available
|
||||
/*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
|
||||
|
||||
bool mTryToConnectToFbc;
|
||||
bool mTryToConnectToFacebook;
|
||||
|
||||
// internals
|
||||
class Updater;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@
|
|||
#include "llsidetraypanelcontainer.h"
|
||||
|
||||
#include "llfloatersnapshot.h" // FIXME: create a snapshot model
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
|
||||
/**
|
||||
* Provides several ways to save a snapshot.
|
||||
|
|
@ -44,6 +48,7 @@ class LLPanelSnapshotOptions
|
|||
public:
|
||||
LLPanelSnapshotOptions();
|
||||
~LLPanelSnapshotOptions();
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ void onOpen(const LLSD& key);
|
||||
/*virtual*/ void onEconomyDataChange() { updateUploadCost(); }
|
||||
|
||||
|
|
@ -54,6 +59,9 @@ private:
|
|||
void onSaveToEmail();
|
||||
void onSaveToInventory();
|
||||
void onSaveToComputer();
|
||||
void onSendToFacebook();
|
||||
void onSendToTwitter();
|
||||
void onSendToFlickr();
|
||||
};
|
||||
|
||||
static LLPanelInjector<LLPanelSnapshotOptions> panel_class("llpanelsnapshotoptions");
|
||||
|
|
@ -73,6 +81,19 @@ LLPanelSnapshotOptions::~LLPanelSnapshotOptions()
|
|||
LLGlobalEconomy::Singleton::getInstance()->removeObserver(this);
|
||||
}
|
||||
|
||||
// virtual
|
||||
BOOL LLPanelSnapshotOptions::postBuild()
|
||||
{
|
||||
LLTextBox* sendToFacebookTextBox = getChild<LLTextBox>("send_to_facebook_textbox");
|
||||
sendToFacebookTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToFacebook, this));
|
||||
LLTextBox* sendToTwitterTextBox = getChild<LLTextBox>("send_to_twitter_textbox");
|
||||
sendToTwitterTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToTwitter, this));
|
||||
LLTextBox* sendToFlickrTextBox = getChild<LLTextBox>("send_to_flickr_textbox");
|
||||
sendToFlickrTextBox->setURLClickedCallback(boost::bind(&LLPanelSnapshotOptions::onSendToFlickr, this));
|
||||
|
||||
return LLPanel::postBuild();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLPanelSnapshotOptions::onOpen(const LLSD& key)
|
||||
{
|
||||
|
|
@ -118,3 +139,39 @@ void LLPanelSnapshotOptions::onSaveToComputer()
|
|||
{
|
||||
openPanel("panel_snapshot_local");
|
||||
}
|
||||
|
||||
void LLPanelSnapshotOptions::onSendToFacebook()
|
||||
{
|
||||
LLFloaterReg::hideInstance("snapshot");
|
||||
|
||||
LLFloaterFacebook* facebook_floater = dynamic_cast<LLFloaterFacebook*>(LLFloaterReg::getInstance("facebook"));
|
||||
if (facebook_floater)
|
||||
{
|
||||
facebook_floater->showPhotoPanel();
|
||||
}
|
||||
LLFloaterReg::showInstance("facebook");
|
||||
}
|
||||
|
||||
void LLPanelSnapshotOptions::onSendToTwitter()
|
||||
{
|
||||
LLFloaterReg::hideInstance("snapshot");
|
||||
|
||||
LLFloaterTwitter* twitter_floater = dynamic_cast<LLFloaterTwitter*>(LLFloaterReg::getInstance("twitter"));
|
||||
if (twitter_floater)
|
||||
{
|
||||
twitter_floater->showPhotoPanel();
|
||||
}
|
||||
LLFloaterReg::showInstance("twitter");
|
||||
}
|
||||
|
||||
void LLPanelSnapshotOptions::onSendToFlickr()
|
||||
{
|
||||
LLFloaterReg::hideInstance("snapshot");
|
||||
|
||||
LLFloaterFlickr* flickr_floater = dynamic_cast<LLFloaterFlickr*>(LLFloaterReg::getInstance("flickr"));
|
||||
if (flickr_floater)
|
||||
{
|
||||
flickr_floater->showPhotoPanel();
|
||||
}
|
||||
LLFloaterReg::showInstance("flickr");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,11 @@
|
|||
#include "lleconomy.h"
|
||||
#include "llfloaterperms.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloatersocial.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llimagefilter.h"
|
||||
#include "llimagefiltersmanager.h"
|
||||
#include "llimagebmp.h"
|
||||
#include "llimagej2c.h"
|
||||
#include "llimagejpeg.h"
|
||||
|
|
@ -70,9 +74,11 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
|
|||
mColor(1.f, 0.f, 0.f, 0.5f),
|
||||
mCurImageIndex(0),
|
||||
mPreviewImage(NULL),
|
||||
mThumbnailImage(NULL) ,
|
||||
mThumbnailImage(NULL) ,
|
||||
mBigThumbnailImage(NULL) ,
|
||||
mThumbnailWidth(0),
|
||||
mThumbnailHeight(0),
|
||||
mThumbnailSubsampled(FALSE),
|
||||
mPreviewImageEncoded(NULL),
|
||||
mFormattedImage(NULL),
|
||||
mShineCountdown(0),
|
||||
|
|
@ -86,7 +92,11 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
|
|||
mCameraPos(LLViewerCamera::getInstance()->getOrigin()),
|
||||
mCameraRot(LLViewerCamera::getInstance()->getQuaternion()),
|
||||
mSnapshotActive(FALSE),
|
||||
mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR)
|
||||
mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR),
|
||||
mFilterName(""),
|
||||
mAllowRenderUI(TRUE),
|
||||
mAllowFullScreenPreview(TRUE),
|
||||
mViewContainer(NULL)
|
||||
{
|
||||
setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality"));
|
||||
mSnapshotDelayTimer.setTimerExpirySec(0.0f);
|
||||
|
|
@ -105,6 +115,7 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLSnapshotLivePreview::Param
|
|||
mKeepAspectRatio = gSavedSettings.getBOOL("KeepAspectForSnapshot") ;
|
||||
mThumbnailUpdateLock = FALSE ;
|
||||
mThumbnailUpToDate = FALSE ;
|
||||
mBigThumbnailUpToDate = FALSE ;
|
||||
}
|
||||
|
||||
LLSnapshotLivePreview::~LLSnapshotLivePreview()
|
||||
|
|
@ -120,14 +131,7 @@ LLSnapshotLivePreview::~LLSnapshotLivePreview()
|
|||
|
||||
void LLSnapshotLivePreview::setMaxImageSize(S32 size)
|
||||
{
|
||||
if(size < MAX_SNAPSHOT_IMAGE_SIZE)
|
||||
{
|
||||
mMaxImageSize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMaxImageSize = MAX_SNAPSHOT_IMAGE_SIZE ;
|
||||
}
|
||||
mMaxImageSize = llmin(size,(S32)(MAX_SNAPSHOT_IMAGE_SIZE));
|
||||
}
|
||||
|
||||
LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
|
||||
|
|
@ -135,97 +139,92 @@ LLViewerTexture* LLSnapshotLivePreview::getCurrentImage()
|
|||
return mViewerImage[mCurImageIndex];
|
||||
}
|
||||
|
||||
F32 LLSnapshotLivePreview::getAspect()
|
||||
{
|
||||
F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
|
||||
F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
|
||||
|
||||
if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
|
||||
{
|
||||
return image_aspect_ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
return window_aspect_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
F32 LLSnapshotLivePreview::getImageAspect()
|
||||
{
|
||||
if (!getCurrentImage())
|
||||
{
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
return getAspect() ;
|
||||
// mKeepAspectRatio) == gSavedSettings.getBOOL("KeepAspectForSnapshot"))
|
||||
return (mKeepAspectRatio ? ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()) : ((F32)getWidth()) / ((F32)getHeight()));
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
|
||||
void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail, F32 delay)
|
||||
{
|
||||
// Invalidate current image.
|
||||
LL_DEBUGS() << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << LL_ENDL;
|
||||
if (getSnapshotUpToDate())
|
||||
{
|
||||
S32 old_image_index = mCurImageIndex;
|
||||
mCurImageIndex = (mCurImageIndex + 1) % 2;
|
||||
setSize(mWidth[old_image_index], mHeight[old_image_index]);
|
||||
mFallAnimTimer.start();
|
||||
}
|
||||
mSnapshotUpToDate = FALSE;
|
||||
|
||||
// Update snapshot source rect depending on whether we keep the aspect ratio.
|
||||
LLRect& rect = mImageRect[mCurImageIndex];
|
||||
rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
|
||||
F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
|
||||
F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
|
||||
|
||||
if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
|
||||
{
|
||||
if (image_aspect_ratio > window_aspect_ratio)
|
||||
{
|
||||
// trim off top and bottom
|
||||
S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio);
|
||||
rect.mBottom += (getRect().getHeight() - new_height) / 2;
|
||||
rect.mTop -= (getRect().getHeight() - new_height) / 2;
|
||||
}
|
||||
else if (image_aspect_ratio < window_aspect_ratio)
|
||||
{
|
||||
// trim off left and right
|
||||
S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio);
|
||||
rect.mLeft += (getRect().getWidth() - new_width) / 2;
|
||||
rect.mRight -= (getRect().getWidth() - new_width) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop shining animation.
|
||||
mShineAnimTimer.stop();
|
||||
lldebugs << "updateSnapshot: mSnapshotUpToDate = " << getSnapshotUpToDate() << llendl;
|
||||
|
||||
// Update snapshot if requested.
|
||||
if (new_snapshot)
|
||||
{
|
||||
if (getSnapshotUpToDate())
|
||||
{
|
||||
S32 old_image_index = mCurImageIndex;
|
||||
mCurImageIndex = (mCurImageIndex + 1) % 2;
|
||||
setSize(mWidth[old_image_index], mHeight[old_image_index]);
|
||||
mFallAnimTimer.start();
|
||||
}
|
||||
mSnapshotUpToDate = FALSE;
|
||||
|
||||
// Update snapshot source rect depending on whether we keep the aspect ratio.
|
||||
LLRect& rect = mImageRect[mCurImageIndex];
|
||||
rect.set(0, getRect().getHeight(), getRect().getWidth(), 0);
|
||||
|
||||
F32 image_aspect_ratio = ((F32)getWidth()) / ((F32)getHeight());
|
||||
F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight());
|
||||
|
||||
if (mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot"))
|
||||
{
|
||||
if (image_aspect_ratio > window_aspect_ratio)
|
||||
{
|
||||
// trim off top and bottom
|
||||
S32 new_height = llround((F32)getRect().getWidth() / image_aspect_ratio);
|
||||
rect.mBottom += (getRect().getHeight() - new_height) / 2;
|
||||
rect.mTop -= (getRect().getHeight() - new_height) / 2;
|
||||
}
|
||||
else if (image_aspect_ratio < window_aspect_ratio)
|
||||
{
|
||||
// trim off left and right
|
||||
S32 new_width = llround((F32)getRect().getHeight() * image_aspect_ratio);
|
||||
rect.mLeft += (getRect().getWidth() - new_width) / 2;
|
||||
rect.mRight -= (getRect().getWidth() - new_width) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop shining animation.
|
||||
mShineAnimTimer.stop();
|
||||
mSnapshotDelayTimer.start();
|
||||
mSnapshotDelayTimer.setTimerExpirySec(delay);
|
||||
LLFloaterSnapshot::preUpdate();
|
||||
LLFloaterSocial::preUpdate();
|
||||
|
||||
// Tell the floater container that the snapshot is in the process of updating itself
|
||||
if (mViewContainer)
|
||||
{
|
||||
mViewContainer->notify(LLSD().with("snapshot-updating", true));
|
||||
}
|
||||
}
|
||||
|
||||
// Update thumbnail if requested.
|
||||
if(new_thumbnail)
|
||||
if (new_thumbnail)
|
||||
{
|
||||
mThumbnailUpToDate = FALSE ;
|
||||
mBigThumbnailUpToDate = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::setSnapshotQuality(S32 quality)
|
||||
// Return true if the quality has been changed, false otherwise
|
||||
bool LLSnapshotLivePreview::setSnapshotQuality(S32 quality, bool set_by_user)
|
||||
{
|
||||
llclamp(quality, 0, 100);
|
||||
if (quality != mSnapshotQuality)
|
||||
{
|
||||
mSnapshotQuality = quality;
|
||||
gSavedSettings.setS32("SnapshotQuality", quality);
|
||||
mSnapshotUpToDate = FALSE;
|
||||
if (set_by_user)
|
||||
{
|
||||
gSavedSettings.setS32("SnapshotQuality", quality);
|
||||
}
|
||||
mFormattedImage = NULL; // Invalidate the already formatted image if any
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::drawPreviewRect(S32 offset_x, S32 offset_y)
|
||||
|
|
@ -459,68 +458,57 @@ void LLSnapshotLivePreview::reshape(S32 width, S32 height, BOOL called_from_pare
|
|||
if (old_rect.getWidth() != width || old_rect.getHeight() != height)
|
||||
{
|
||||
LL_DEBUGS() << "window reshaped, updating thumbnail" << LL_ENDL;
|
||||
updateSnapshot(FALSE, TRUE);
|
||||
updateSnapshot(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLSnapshotLivePreview::setThumbnailImageSize()
|
||||
{
|
||||
if(getWidth() < 10 || getHeight() < 10)
|
||||
if (getWidth() < 10 || getHeight() < 10)
|
||||
{
|
||||
return FALSE ;
|
||||
}
|
||||
S32 window_width = gViewerWindow->getWindowWidthRaw() ;
|
||||
S32 window_height = gViewerWindow->getWindowHeightRaw() ;
|
||||
S32 width = (mThumbnailSubsampled ? mPreviewImage->getWidth() : gViewerWindow->getWindowWidthRaw());
|
||||
S32 height = (mThumbnailSubsampled ? mPreviewImage->getHeight() : gViewerWindow->getWindowHeightRaw()) ;
|
||||
|
||||
F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height);
|
||||
F32 aspect_ratio = ((F32)width) / ((F32)height);
|
||||
|
||||
// UI size for thumbnail
|
||||
// *FIXME: the rect does not change, so maybe there's no need to recalculate max w/h.
|
||||
const LLRect& thumbnail_rect = mThumbnailPlaceholderRect;
|
||||
S32 max_width = thumbnail_rect.getWidth();
|
||||
S32 max_height = thumbnail_rect.getHeight();
|
||||
S32 max_width = mThumbnailPlaceholderRect.getWidth();
|
||||
S32 max_height = mThumbnailPlaceholderRect.getHeight();
|
||||
|
||||
if (window_aspect_ratio > (F32)max_width / max_height)
|
||||
if (aspect_ratio > (F32)max_width / (F32)max_height)
|
||||
{
|
||||
// image too wide, shrink to width
|
||||
mThumbnailWidth = max_width;
|
||||
mThumbnailHeight = llround((F32)max_width / window_aspect_ratio);
|
||||
mThumbnailHeight = llround((F32)max_width / aspect_ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
// image too tall, shrink to height
|
||||
mThumbnailHeight = max_height;
|
||||
mThumbnailWidth = llround((F32)max_height * window_aspect_ratio);
|
||||
mThumbnailWidth = llround((F32)max_height * aspect_ratio);
|
||||
}
|
||||
|
||||
if(mThumbnailWidth > window_width || mThumbnailHeight > window_height)
|
||||
|
||||
if (mThumbnailWidth > width || mThumbnailHeight > height)
|
||||
{
|
||||
return FALSE ;//if the window is too small, ignore thumbnail updating.
|
||||
}
|
||||
|
||||
S32 left = 0 , top = mThumbnailHeight, right = mThumbnailWidth, bottom = 0 ;
|
||||
if(!mKeepAspectRatio)
|
||||
if (!mKeepAspectRatio)
|
||||
{
|
||||
F32 ratio_x = (F32)getWidth() / window_width ;
|
||||
F32 ratio_y = (F32)getHeight() / window_height ;
|
||||
F32 ratio_x = (F32)getWidth() / width ;
|
||||
F32 ratio_y = (F32)getHeight() / height ;
|
||||
|
||||
//if(getWidth() > window_width ||
|
||||
// getHeight() > window_height )
|
||||
{
|
||||
if(ratio_x > ratio_y)
|
||||
{
|
||||
top = (S32)(top * ratio_y / ratio_x) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = (S32)(right * ratio_x / ratio_y) ;
|
||||
}
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// right = (S32)(right * ratio_x) ;
|
||||
// top = (S32)(top * ratio_y) ;
|
||||
//}
|
||||
if (ratio_x > ratio_y)
|
||||
{
|
||||
top = (S32)(top * ratio_y / ratio_x) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = (S32)(right * ratio_x / ratio_y) ;
|
||||
}
|
||||
left = (S32)((mThumbnailWidth - right) * 0.5f) ;
|
||||
bottom = (S32)((mThumbnailHeight - top) * 0.5f) ;
|
||||
top += bottom ;
|
||||
|
|
@ -556,25 +544,62 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
|
|||
return ;
|
||||
}
|
||||
|
||||
// Invalidate the big thumbnail when we regenerate the small one
|
||||
mBigThumbnailUpToDate = FALSE;
|
||||
|
||||
if(mThumbnailImage)
|
||||
{
|
||||
resetThumbnailImage() ;
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
if(!gViewerWindow->thumbnailSnapshot(raw,
|
||||
mThumbnailWidth, mThumbnailHeight,
|
||||
gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
mSnapshotBufferType) )
|
||||
|
||||
if (mThumbnailSubsampled)
|
||||
{
|
||||
// The thumbnail is be a subsampled version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
|
||||
raw->resize( mPreviewImage->getWidth(),
|
||||
mPreviewImage->getHeight(),
|
||||
mPreviewImage->getComponents());
|
||||
raw->copy(mPreviewImage);
|
||||
// Scale to the thumbnail size
|
||||
if (!raw->scale(mThumbnailWidth, mThumbnailHeight))
|
||||
{
|
||||
raw = NULL ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The thumbnail is a screen view with screen grab positioning preview
|
||||
if(!gViewerWindow->thumbnailSnapshot(raw,
|
||||
mThumbnailWidth, mThumbnailHeight,
|
||||
mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
mSnapshotBufferType) )
|
||||
{
|
||||
raw = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
if (raw)
|
||||
{
|
||||
raw = NULL ;
|
||||
}
|
||||
|
||||
if(raw)
|
||||
{
|
||||
raw->expandToPowerOfTwo();
|
||||
mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
|
||||
// Filter the thumbnail
|
||||
// Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
|
||||
if (getFilter() != "")
|
||||
{
|
||||
std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
|
||||
if (filter_path != "")
|
||||
{
|
||||
LLImageFilter filter(filter_path);
|
||||
filter.executeFilter(raw);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
|
||||
}
|
||||
}
|
||||
// Scale to a power of 2 so it can be mapped to a texture
|
||||
raw->expandToPowerOfTwo();
|
||||
mThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
|
||||
mThumbnailUpToDate = TRUE ;
|
||||
}
|
||||
|
||||
|
|
@ -582,6 +607,52 @@ void LLSnapshotLivePreview::generateThumbnailImage(BOOL force_update)
|
|||
mThumbnailUpdateLock = FALSE ;
|
||||
}
|
||||
|
||||
LLViewerTexture* LLSnapshotLivePreview::getBigThumbnailImage()
|
||||
{
|
||||
if (mThumbnailUpdateLock) //in the process of updating
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
if (mBigThumbnailUpToDate && mBigThumbnailImage)//already updated
|
||||
{
|
||||
return mBigThumbnailImage;
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> raw = new LLImageRaw;
|
||||
|
||||
if (raw)
|
||||
{
|
||||
// The big thumbnail is a new filtered version of the preview (used in SL Share previews, i.e. Flickr, Twitter, Facebook)
|
||||
mBigThumbnailWidth = mPreviewImage->getWidth();
|
||||
mBigThumbnailHeight = mPreviewImage->getHeight();
|
||||
raw->resize( mBigThumbnailWidth,
|
||||
mBigThumbnailHeight,
|
||||
mPreviewImage->getComponents());
|
||||
raw->copy(mPreviewImage);
|
||||
|
||||
// Filter
|
||||
// Note: filtering needs to be done *before* the scaling to power of 2 or the effect is distorted
|
||||
if (getFilter() != "")
|
||||
{
|
||||
std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
|
||||
if (filter_path != "")
|
||||
{
|
||||
LLImageFilter filter(filter_path);
|
||||
filter.executeFilter(raw);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
|
||||
}
|
||||
}
|
||||
// Scale to a power of 2 so it can be mapped to a texture
|
||||
raw->expandToPowerOfTwo();
|
||||
mBigThumbnailImage = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
|
||||
mBigThumbnailUpToDate = TRUE ;
|
||||
}
|
||||
|
||||
return mBigThumbnailImage ;
|
||||
}
|
||||
|
||||
// Called often. Checks whether it's time to grab a new snapshot and if so, does it.
|
||||
// Returns TRUE if new snapshot generated, FALSE otherwise.
|
||||
|
|
@ -598,7 +669,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
|
|||
// If we're in freeze-frame mode and camera has moved, update snapshot.
|
||||
LLVector3 new_camera_pos = LLViewerCamera::getInstance()->getOrigin();
|
||||
LLQuaternion new_camera_rot = LLViewerCamera::getInstance()->getQuaternion();
|
||||
if (gSavedSettings.getBOOL("FreezeTime") &&
|
||||
if (gSavedSettings.getBOOL("FreezeTime") && previewp->mAllowFullScreenPreview &&
|
||||
(new_camera_pos != previewp->mCameraPos || dot(new_camera_rot, previewp->mCameraRot) < 0.995f))
|
||||
{
|
||||
previewp->mCameraPos = new_camera_pos;
|
||||
|
|
@ -616,157 +687,256 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview )
|
|||
previewp->mSnapshotActive =
|
||||
(previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired())
|
||||
&& !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active
|
||||
if ( ! previewp->mSnapshotActive)
|
||||
if (!previewp->mSnapshotActive && previewp->getSnapshotUpToDate() && previewp->getThumbnailUpToDate())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// time to produce a snapshot
|
||||
previewp->setThumbnailImageSize();
|
||||
if(!previewp->getSnapshotUpToDate())
|
||||
{
|
||||
lldebugs << "producing snapshot" << llendl;
|
||||
if (!previewp->mPreviewImage)
|
||||
{
|
||||
previewp->mPreviewImage = new LLImageRaw;
|
||||
}
|
||||
|
||||
LL_DEBUGS() << "producing snapshot" << LL_ENDL;
|
||||
if (!previewp->mPreviewImage)
|
||||
previewp->setVisible(FALSE);
|
||||
previewp->setEnabled(FALSE);
|
||||
|
||||
previewp->getWindow()->incBusyCount();
|
||||
previewp->setImageScaled(FALSE);
|
||||
|
||||
// grab the raw image
|
||||
if (gViewerWindow->rawSnapshot(
|
||||
previewp->mPreviewImage,
|
||||
previewp->getWidth(),
|
||||
previewp->getHeight(),
|
||||
previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
|
||||
previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
|
||||
previewp->mAllowRenderUI && gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
previewp->mSnapshotBufferType,
|
||||
previewp->getMaxImageSize()))
|
||||
{
|
||||
// Invalidate/delete any existing encoded image
|
||||
previewp->mPreviewImageEncoded = NULL;
|
||||
// Invalidate/delete any existing formatted image
|
||||
previewp->mFormattedImage = NULL;
|
||||
// Update the data size
|
||||
previewp->estimateDataSize();
|
||||
|
||||
// Full size preview is set: get the decoded image result and save it for animation
|
||||
if (gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview)
|
||||
{
|
||||
// Get the decoded version of the formatted image
|
||||
previewp->getEncodedImage();
|
||||
|
||||
// We need to scale that a bit for display...
|
||||
LLPointer<LLImageRaw> scaled = new LLImageRaw(
|
||||
previewp->mPreviewImageEncoded->getData(),
|
||||
previewp->mPreviewImageEncoded->getWidth(),
|
||||
previewp->mPreviewImageEncoded->getHeight(),
|
||||
previewp->mPreviewImageEncoded->getComponents());
|
||||
|
||||
if (!scaled->isBufferInvalid())
|
||||
{
|
||||
// leave original image dimensions, just scale up texture buffer
|
||||
if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
|
||||
{
|
||||
// go ahead and shrink image to appropriate power of 2 for display
|
||||
scaled->biasedScaleToPowerOfTwo(1024);
|
||||
previewp->setImageScaled(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// expand image but keep original image data intact
|
||||
scaled->expandToPowerOfTwo(1024, FALSE);
|
||||
}
|
||||
|
||||
previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
|
||||
LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
|
||||
gGL.getTexUnit(0)->bind(curr_preview_image);
|
||||
curr_preview_image->setFilteringOption(previewp->getSnapshotType() == SNAPSHOT_TEXTURE ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
|
||||
curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
|
||||
previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
|
||||
previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
|
||||
}
|
||||
}
|
||||
// The snapshot is updated now...
|
||||
previewp->mSnapshotUpToDate = TRUE;
|
||||
|
||||
// We need to update the thumbnail though
|
||||
previewp->setThumbnailImageSize();
|
||||
previewp->generateThumbnailImage(TRUE) ;
|
||||
}
|
||||
previewp->getWindow()->decBusyCount();
|
||||
previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame") && previewp->mAllowFullScreenPreview); // only show fullscreen preview when in freeze frame mode
|
||||
previewp->mSnapshotDelayTimer.stop();
|
||||
previewp->mSnapshotActive = FALSE;
|
||||
lldebugs << "done creating snapshot" << llendl;
|
||||
}
|
||||
|
||||
if (!previewp->getThumbnailUpToDate())
|
||||
{
|
||||
previewp->mPreviewImage = new LLImageRaw;
|
||||
previewp->generateThumbnailImage() ;
|
||||
}
|
||||
|
||||
// Tell the floater container that the snapshot is updated now
|
||||
if (previewp->mViewContainer)
|
||||
{
|
||||
previewp->mViewContainer->notify(LLSD().with("snapshot-updated", true));
|
||||
}
|
||||
|
||||
if (!previewp->mPreviewImageEncoded)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
S32 LLSnapshotLivePreview::getEncodedImageWidth() const
|
||||
{
|
||||
S32 width = getWidth();
|
||||
if (getSnapshotType() == SNAPSHOT_TEXTURE)
|
||||
{
|
||||
width = LLImageRaw::biasedDimToPowerOfTwo(width,MAX_TEXTURE_SIZE);
|
||||
}
|
||||
return width;
|
||||
}
|
||||
S32 LLSnapshotLivePreview::getEncodedImageHeight() const
|
||||
{
|
||||
S32 height = getHeight();
|
||||
if (getSnapshotType() == SNAPSHOT_TEXTURE)
|
||||
{
|
||||
height = LLImageRaw::biasedDimToPowerOfTwo(height,MAX_TEXTURE_SIZE);
|
||||
}
|
||||
return height;
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> LLSnapshotLivePreview::getEncodedImage()
|
||||
{
|
||||
if (!mPreviewImageEncoded)
|
||||
{
|
||||
previewp->mPreviewImageEncoded = new LLImageRaw;
|
||||
}
|
||||
|
||||
previewp->setVisible(FALSE);
|
||||
previewp->setEnabled(FALSE);
|
||||
|
||||
previewp->getWindow()->incBusyCount();
|
||||
previewp->setImageScaled(FALSE);
|
||||
|
||||
// grab the raw image and encode it into desired format
|
||||
if(gViewerWindow->rawSnapshot(
|
||||
previewp->mPreviewImage,
|
||||
previewp->getWidth(),
|
||||
previewp->getHeight(),
|
||||
previewp->mKeepAspectRatio,//gSavedSettings.getBOOL("KeepAspectForSnapshot"),
|
||||
previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE,
|
||||
gSavedSettings.getBOOL("RenderUIInSnapshot"),
|
||||
FALSE,
|
||||
previewp->mSnapshotBufferType,
|
||||
previewp->getMaxImageSize()))
|
||||
{
|
||||
previewp->mPreviewImageEncoded->resize(
|
||||
previewp->mPreviewImage->getWidth(),
|
||||
previewp->mPreviewImage->getHeight(),
|
||||
previewp->mPreviewImage->getComponents());
|
||||
|
||||
if(previewp->getSnapshotType() == SNAPSHOT_TEXTURE)
|
||||
mPreviewImageEncoded = new LLImageRaw;
|
||||
|
||||
mPreviewImageEncoded->resize(
|
||||
mPreviewImage->getWidth(),
|
||||
mPreviewImage->getHeight(),
|
||||
mPreviewImage->getComponents());
|
||||
|
||||
if (getSnapshotType() == SNAPSHOT_TEXTURE)
|
||||
{
|
||||
// We don't store the intermediate formatted image in mFormattedImage in the J2C case
|
||||
LL_DEBUGS() << "Encoding new image of format J2C" << LL_ENDL;
|
||||
LLPointer<LLImageJ2C> formatted = new LLImageJ2C;
|
||||
// Copy the preview
|
||||
LLPointer<LLImageRaw> scaled = new LLImageRaw(
|
||||
previewp->mPreviewImage->getData(),
|
||||
previewp->mPreviewImage->getWidth(),
|
||||
previewp->mPreviewImage->getHeight(),
|
||||
previewp->mPreviewImage->getComponents());
|
||||
|
||||
mPreviewImage->getData(),
|
||||
mPreviewImage->getWidth(),
|
||||
mPreviewImage->getHeight(),
|
||||
mPreviewImage->getComponents());
|
||||
// Scale it as required by J2C
|
||||
scaled->biasedScaleToPowerOfTwo(MAX_TEXTURE_SIZE);
|
||||
previewp->setImageScaled(TRUE);
|
||||
setImageScaled(TRUE);
|
||||
// Compress to J2C
|
||||
if (formatted->encode(scaled, 0.f))
|
||||
{
|
||||
previewp->mDataSize = formatted->getDataSize();
|
||||
formatted->decode(previewp->mPreviewImageEncoded, 0);
|
||||
// We can update the data size precisely at that point
|
||||
mDataSize = formatted->getDataSize();
|
||||
// Decompress back
|
||||
formatted->decode(mPreviewImageEncoded, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete any existing image
|
||||
previewp->mFormattedImage = NULL;
|
||||
// now create the new one of the appropriate format.
|
||||
LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotFormat();
|
||||
LL_DEBUGS() << "Encoding new image of format " << format << LL_ENDL;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
|
||||
previewp->mFormattedImage = new LLImagePNG();
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
|
||||
previewp->mFormattedImage = new LLImageJPEG(previewp->mSnapshotQuality);
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
|
||||
previewp->mFormattedImage = new LLImageBMP();
|
||||
break;
|
||||
}
|
||||
if (previewp->mFormattedImage->encode(previewp->mPreviewImage, 0))
|
||||
{
|
||||
previewp->mDataSize = previewp->mFormattedImage->getDataSize();
|
||||
// special case BMP to copy instead of decode otherwise decode will crash.
|
||||
if(format == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
|
||||
{
|
||||
previewp->mPreviewImageEncoded->copy(previewp->mPreviewImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
previewp->mFormattedImage->decode(previewp->mPreviewImageEncoded, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLPointer<LLImageRaw> scaled = new LLImageRaw(
|
||||
previewp->mPreviewImageEncoded->getData(),
|
||||
previewp->mPreviewImageEncoded->getWidth(),
|
||||
previewp->mPreviewImageEncoded->getHeight(),
|
||||
previewp->mPreviewImageEncoded->getComponents());
|
||||
|
||||
if(!scaled->isBufferInvalid())
|
||||
{
|
||||
// leave original image dimensions, just scale up texture buffer
|
||||
if (previewp->mPreviewImageEncoded->getWidth() > 1024 || previewp->mPreviewImageEncoded->getHeight() > 1024)
|
||||
{
|
||||
// go ahead and shrink image to appropriate power of 2 for display
|
||||
scaled->biasedScaleToPowerOfTwo(1024);
|
||||
previewp->setImageScaled(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// expand image but keep original image data intact
|
||||
scaled->expandToPowerOfTwo(1024, FALSE);
|
||||
}
|
||||
|
||||
previewp->mViewerImage[previewp->mCurImageIndex] = LLViewerTextureManager::getLocalTexture(scaled.get(), FALSE);
|
||||
LLPointer<LLViewerTexture> curr_preview_image = previewp->mViewerImage[previewp->mCurImageIndex];
|
||||
gGL.getTexUnit(0)->bind(curr_preview_image);
|
||||
if (previewp->getSnapshotType() != SNAPSHOT_TEXTURE)
|
||||
{
|
||||
curr_preview_image->setFilteringOption(LLTexUnit::TFO_POINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
curr_preview_image->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
|
||||
}
|
||||
curr_preview_image->setAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
|
||||
previewp->mSnapshotUpToDate = TRUE;
|
||||
previewp->generateThumbnailImage(TRUE) ;
|
||||
|
||||
previewp->mPosTakenGlobal = gAgentCamera.getCameraPositionGlobal();
|
||||
previewp->mShineCountdown = 4; // wait a few frames to avoid animation glitch due to readback this frame
|
||||
// Update mFormattedImage if necessary
|
||||
getFormattedImage();
|
||||
if (getSnapshotFormat() == LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP)
|
||||
{
|
||||
// BMP hack : copy instead of decode otherwise decode will crash.
|
||||
mPreviewImageEncoded->copy(mPreviewImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decode back
|
||||
mFormattedImage->decode(mPreviewImageEncoded, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
previewp->getWindow()->decBusyCount();
|
||||
// only show fullscreen preview when in freeze frame mode
|
||||
previewp->setVisible(gSavedSettings.getBOOL("UseFreezeFrame"));
|
||||
previewp->mSnapshotDelayTimer.stop();
|
||||
previewp->mSnapshotActive = FALSE;
|
||||
return mPreviewImageEncoded;
|
||||
}
|
||||
|
||||
if(!previewp->getThumbnailUpToDate())
|
||||
{
|
||||
previewp->generateThumbnailImage() ;
|
||||
}
|
||||
LL_DEBUGS() << "done creating snapshot" << LL_ENDL;
|
||||
LLFloaterSnapshot::postUpdate();
|
||||
LLFloaterSocial::postUpdate();
|
||||
// We actually estimate the data size so that we do not require actual compression when showing the preview
|
||||
// Note : whenever formatted image is computed, mDataSize will be updated to reflect the true size
|
||||
void LLSnapshotLivePreview::estimateDataSize()
|
||||
{
|
||||
// Compression ratio
|
||||
F32 ratio = 1.0;
|
||||
|
||||
if (getSnapshotType() == SNAPSHOT_TEXTURE)
|
||||
{
|
||||
ratio = 8.0; // This is what we shoot for when compressing to J2C
|
||||
}
|
||||
else
|
||||
{
|
||||
LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
|
||||
switch (format)
|
||||
{
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
|
||||
ratio = 3.0; // Average observed PNG compression ratio
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
|
||||
// Observed from JPG compression tests
|
||||
ratio = (110 - mSnapshotQuality) / 2;
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
|
||||
ratio = 1.0; // No compression with BMP
|
||||
break;
|
||||
}
|
||||
}
|
||||
mDataSize = (S32)((F32)mPreviewImage->getDataSize() / ratio);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
LLPointer<LLImageFormatted> LLSnapshotLivePreview::getFormattedImage()
|
||||
{
|
||||
if (!mFormattedImage)
|
||||
{
|
||||
// Apply the filter to mPreviewImage
|
||||
if (getFilter() != "")
|
||||
{
|
||||
std::string filter_path = LLImageFiltersManager::getInstance()->getFilterPath(getFilter());
|
||||
if (filter_path != "")
|
||||
{
|
||||
LLImageFilter filter(filter_path);
|
||||
filter.executeFilter(mPreviewImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Couldn't find a path to the following filter : " << getFilter() << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the new formatted image of the appropriate format.
|
||||
LLFloaterSnapshot::ESnapshotFormat format = getSnapshotFormat();
|
||||
lldebugs << "Encoding new image of format " << format << llendl;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
|
||||
mFormattedImage = new LLImagePNG();
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
|
||||
mFormattedImage = new LLImageJPEG(mSnapshotQuality);
|
||||
break;
|
||||
case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
|
||||
mFormattedImage = new LLImageBMP();
|
||||
break;
|
||||
}
|
||||
if (mFormattedImage->encode(mPreviewImage, 0))
|
||||
{
|
||||
// We can update the data size precisely at that point
|
||||
mDataSize = mFormattedImage->getDataSize();
|
||||
}
|
||||
}
|
||||
return mFormattedImage;
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::setSize(S32 w, S32 h)
|
||||
|
|
@ -776,6 +946,15 @@ void LLSnapshotLivePreview::setSize(S32 w, S32 h)
|
|||
setHeight(h);
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format)
|
||||
{
|
||||
if (mSnapshotFormat != format)
|
||||
{
|
||||
mFormattedImage = NULL; // Invalidate the already formatted image if any
|
||||
mSnapshotFormat = format;
|
||||
}
|
||||
}
|
||||
|
||||
void LLSnapshotLivePreview::getSize(S32& w, S32& h) const
|
||||
{
|
||||
w = getWidth();
|
||||
|
|
@ -836,6 +1015,10 @@ void LLSnapshotLivePreview::saveTexture()
|
|||
|
||||
BOOL LLSnapshotLivePreview::saveLocal()
|
||||
{
|
||||
// Update mFormattedImage if necessary
|
||||
getFormattedImage();
|
||||
|
||||
// Save the formatted image
|
||||
BOOL success = gViewerWindow->saveImageNumbered(mFormattedImage);
|
||||
|
||||
if(success)
|
||||
|
|
@ -844,3 +1027,4 @@ BOOL LLSnapshotLivePreview::saveLocal()
|
|||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#define LL_LLSNAPSHOTLIVEPREVIEW_H
|
||||
|
||||
#include "llpanelsnapshot.h"
|
||||
#include "llviewertexture.h"
|
||||
#include "llviewerwindow.h"
|
||||
|
||||
class LLImageJPEG;
|
||||
|
|
@ -62,6 +63,8 @@ public:
|
|||
LLSnapshotLivePreview(const LLSnapshotLivePreview::Params& p);
|
||||
~LLSnapshotLivePreview();
|
||||
|
||||
void setContainer(LLView* container) { mViewContainer = container; }
|
||||
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent);
|
||||
|
||||
|
|
@ -71,6 +74,9 @@ public:
|
|||
void getSize(S32& w, S32& h) const;
|
||||
S32 getWidth() const { return mWidth[mCurImageIndex]; }
|
||||
S32 getHeight() const { return mHeight[mCurImageIndex]; }
|
||||
S32 getEncodedImageWidth() const;
|
||||
S32 getEncodedImageHeight() const;
|
||||
void estimateDataSize();
|
||||
S32 getDataSize() const { return mDataSize; }
|
||||
void setMaxImageSize(S32 size) ;
|
||||
S32 getMaxImageSize() {return mMaxImageSize ;}
|
||||
|
|
@ -84,36 +90,48 @@ public:
|
|||
S32 getThumbnailHeight() const { return mThumbnailHeight ; }
|
||||
BOOL getThumbnailLock() const { return mThumbnailUpdateLock ; }
|
||||
BOOL getThumbnailUpToDate() const { return mThumbnailUpToDate ;}
|
||||
void setThumbnailSubsampled(BOOL subsampled) { mThumbnailSubsampled = subsampled; }
|
||||
|
||||
LLViewerTexture* getCurrentImage();
|
||||
F32 getImageAspect();
|
||||
F32 getAspect() ;
|
||||
const LLRect& getImageRect() const { return mImageRect[mCurImageIndex]; }
|
||||
BOOL isImageScaled() const { return mImageScaled[mCurImageIndex]; }
|
||||
void setImageScaled(BOOL scaled) { mImageScaled[mCurImageIndex] = scaled; }
|
||||
const LLVector3d& getPosTakenGlobal() const { return mPosTakenGlobal; }
|
||||
|
||||
void setSnapshotType(ESnapshotType type) { mSnapshotType = type; }
|
||||
void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat type) { mSnapshotFormat = type; }
|
||||
void setSnapshotQuality(S32 quality);
|
||||
void setSnapshotFormat(LLFloaterSnapshot::ESnapshotFormat format);
|
||||
bool setSnapshotQuality(S32 quality, bool set_by_user = true);
|
||||
void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; }
|
||||
void setAllowRenderUI(BOOL allow) { mAllowRenderUI = allow; }
|
||||
void setAllowFullScreenPreview(BOOL allow) { mAllowFullScreenPreview = allow; }
|
||||
void setFilter(std::string filter_name) { mFilterName = filter_name; }
|
||||
std::string getFilter() const { return mFilterName; }
|
||||
void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f);
|
||||
void saveTexture();
|
||||
BOOL saveLocal();
|
||||
|
||||
LLPointer<LLImageFormatted> getFormattedImage() const { return mFormattedImage; }
|
||||
LLPointer<LLImageRaw> getEncodedImage() const { return mPreviewImageEncoded; }
|
||||
LLPointer<LLImageFormatted> getFormattedImage();
|
||||
LLPointer<LLImageRaw> getEncodedImage();
|
||||
|
||||
/// Sets size of preview thumbnail image and thhe surrounding rect.
|
||||
/// Sets size of preview thumbnail image and the surrounding rect.
|
||||
void setThumbnailPlaceholderRect(const LLRect& rect) {mThumbnailPlaceholderRect = rect; }
|
||||
BOOL setThumbnailImageSize() ;
|
||||
void generateThumbnailImage(BOOL force_update = FALSE) ;
|
||||
void resetThumbnailImage() { mThumbnailImage = NULL ; }
|
||||
void drawPreviewRect(S32 offset_x, S32 offset_y) ;
|
||||
|
||||
|
||||
LLViewerTexture* getBigThumbnailImage();
|
||||
S32 getBigThumbnailWidth() const { return mBigThumbnailWidth ; }
|
||||
S32 getBigThumbnailHeight() const { return mBigThumbnailHeight ; }
|
||||
|
||||
// Returns TRUE when snapshot generated, FALSE otherwise.
|
||||
static BOOL onIdle( void* snapshot_preview );
|
||||
|
||||
private:
|
||||
LLView* mViewContainer;
|
||||
|
||||
LLColor4 mColor;
|
||||
LLPointer<LLViewerTexture> mViewerImage[2]; //used to represent the scene when the frame is frozen.
|
||||
LLRect mImageRect[2];
|
||||
|
|
@ -130,11 +148,20 @@ private:
|
|||
BOOL mThumbnailUpdateLock ;
|
||||
BOOL mThumbnailUpToDate ;
|
||||
LLRect mThumbnailPlaceholderRect;
|
||||
BOOL mThumbnailSubsampled; // TRUE if the thumbnail is a subsampled version of the mPreviewImage
|
||||
|
||||
LLPointer<LLViewerTexture> mBigThumbnailImage ;
|
||||
S32 mBigThumbnailWidth;
|
||||
S32 mBigThumbnailHeight;
|
||||
BOOL mBigThumbnailUpToDate;
|
||||
|
||||
S32 mCurImageIndex;
|
||||
// The logic is mPreviewImage (raw frame) -> mFormattedImage (formatted / filtered) -> mPreviewImageEncoded (decoded back, to show artifacts)
|
||||
LLPointer<LLImageRaw> mPreviewImage;
|
||||
LLPointer<LLImageRaw> mPreviewImageEncoded;
|
||||
LLPointer<LLImageFormatted> mFormattedImage;
|
||||
BOOL mAllowRenderUI;
|
||||
BOOL mAllowFullScreenPreview;
|
||||
LLFrameTimer mSnapshotDelayTimer;
|
||||
S32 mShineCountdown;
|
||||
LLFrameTimer mShineAnimTimer;
|
||||
|
|
@ -151,6 +178,7 @@ private:
|
|||
LLQuaternion mCameraRot;
|
||||
BOOL mSnapshotActive;
|
||||
LLViewerWindow::ESnapshotType mSnapshotBufferType;
|
||||
std::string mFilterName;
|
||||
|
||||
public:
|
||||
static std::set<LLSnapshotLivePreview*> sList;
|
||||
|
|
|
|||
|
|
@ -2608,7 +2608,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const
|
|||
|
||||
S32 desired_size;
|
||||
std::string exten = gDirUtilp->getExtension(url);
|
||||
if (f_type == FTT_SERVER_BAKE)
|
||||
//if (f_type == FTT_SERVER_BAKE)
|
||||
if ((f_type == FTT_SERVER_BAKE) && !url.empty() && !exten.empty() && (LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C))
|
||||
{
|
||||
// SH-4030: This case should be redundant with the following one, just
|
||||
// breaking it out here to clarify that it's intended behavior.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,503 @@
|
|||
/**
|
||||
* @file lltwitterconnect.h
|
||||
* @author Merov, Cho
|
||||
* @brief Connection to Twitter Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "lltwitterconnect.h"
|
||||
|
||||
#include "llagent.h"
|
||||
#include "llcallingcard.h" // for LLAvatarTracker
|
||||
#include "llcommandhandler.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llimagejpeg.h"
|
||||
#include "lltrans.h"
|
||||
#include "llevents.h"
|
||||
#include "llviewerregion.h"
|
||||
|
||||
#include "llfloaterwebcontent.h"
|
||||
#include "llfloaterreg.h"
|
||||
|
||||
boost::scoped_ptr<LLEventPump> LLTwitterConnect::sStateWatcher(new LLEventStream("TwitterConnectState"));
|
||||
boost::scoped_ptr<LLEventPump> LLTwitterConnect::sInfoWatcher(new LLEventStream("TwitterConnectInfo"));
|
||||
boost::scoped_ptr<LLEventPump> LLTwitterConnect::sContentWatcher(new LLEventStream("TwitterConnectContent"));
|
||||
|
||||
// Local functions
|
||||
void log_twitter_connect_error(const std::string& request, U32 status, const std::string& reason, const std::string& code, const std::string& description)
|
||||
{
|
||||
// Note: 302 (redirect) is *not* an error that warrants logging
|
||||
if (status != 302)
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << request << " request failed with a " << status << " " << reason << ". Reason: " << code << " (" << description << ")" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void toast_user_for_twitter_success()
|
||||
{
|
||||
LLSD args;
|
||||
args["MESSAGE"] = LLTrans::getString("twitter_post_success");
|
||||
LLNotificationsUtil::add("TwitterConnect", args);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLTwitterConnectResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLTwitterConnectResponder);
|
||||
public:
|
||||
|
||||
LLTwitterConnectResponder()
|
||||
{
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_DEBUGS("TwitterConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLTwitterConnect::instance().openTwitterWeb(location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_twitter_connect_error("Connect", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLTwitterShareResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLTwitterShareResponder);
|
||||
public:
|
||||
|
||||
LLTwitterShareResponder()
|
||||
{
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTING);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
toast_user_for_twitter_success();
|
||||
LL_DEBUGS("TwitterConnect") << "Post successful. " << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POSTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLTwitterConnect::instance().openTwitterWeb(location);
|
||||
}
|
||||
}
|
||||
else if ( HTTP_NOT_FOUND == getStatus() )
|
||||
{
|
||||
LLTwitterConnect::instance().connectToTwitter();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_POST_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_twitter_connect_error("Share", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLTwitterDisconnectResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLTwitterDisconnectResponder);
|
||||
public:
|
||||
|
||||
LLTwitterDisconnectResponder()
|
||||
{
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECTING);
|
||||
}
|
||||
|
||||
void setUserDisconnected()
|
||||
{
|
||||
// Clear data
|
||||
LLTwitterConnect::instance().clearInfo();
|
||||
|
||||
//Notify state change
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_DEBUGS("TwitterConnect") << "Disconnect successful. " << dumpResponse() << LL_ENDL;
|
||||
setUserDisconnected();
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
//User not found so already disconnected
|
||||
if ( HTTP_NOT_FOUND == getStatus() )
|
||||
{
|
||||
LL_DEBUGS("TwitterConnect") << "Already disconnected. " << dumpResponse() << LL_ENDL;
|
||||
setUserDisconnected();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_DISCONNECT_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_twitter_connect_error("Disconnect", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLTwitterConnectedResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLTwitterConnectedResponder);
|
||||
public:
|
||||
|
||||
LLTwitterConnectedResponder(bool auto_connect) : mAutoConnect(auto_connect)
|
||||
{
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_IN_PROGRESS);
|
||||
}
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_DEBUGS("TwitterConnect") << "Connect successful. " << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTED);
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
// show the facebook login page if not connected yet
|
||||
if ( HTTP_NOT_FOUND == getStatus() )
|
||||
{
|
||||
LL_DEBUGS("TwitterConnect") << "Not connected. " << dumpResponse() << LL_ENDL;
|
||||
if (mAutoConnect)
|
||||
{
|
||||
LLTwitterConnect::instance().connectToTwitter();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_NOT_CONNECTED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().setConnectionState(LLTwitterConnect::TWITTER_CONNECTION_FAILED);
|
||||
const LLSD& content = getContent();
|
||||
log_twitter_connect_error("Connected", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool mAutoConnect;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
class LLTwitterInfoResponder : public LLHTTPClient::Responder
|
||||
{
|
||||
LOG_CLASS(LLTwitterInfoResponder);
|
||||
public:
|
||||
|
||||
/* virtual */ void httpSuccess()
|
||||
{
|
||||
LL_INFOS("TwitterConnect") << "Twitter: Info received" << LL_ENDL;
|
||||
LL_DEBUGS("TwitterConnect") << "Getting Twitter info successful. " << dumpResponse() << LL_ENDL;
|
||||
LLTwitterConnect::instance().storeInfo(getContent());
|
||||
}
|
||||
|
||||
/* virtual */ void httpFailure()
|
||||
{
|
||||
if ( HTTP_FOUND == getStatus() )
|
||||
{
|
||||
const std::string& location = getResponseHeader(HTTP_IN_HEADER_LOCATION);
|
||||
if (location.empty())
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << "Missing Location header " << dumpResponse()
|
||||
<< "[headers:" << getResponseHeaders() << "]" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LLTwitterConnect::instance().openTwitterWeb(location);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("TwitterConnect") << dumpResponse() << LL_ENDL;
|
||||
const LLSD& content = getContent();
|
||||
log_twitter_connect_error("Info", getStatus(), getReason(),
|
||||
content.get("error_code"), content.get("error_description"));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
LLTwitterConnect::LLTwitterConnect()
|
||||
: mConnectionState(TWITTER_NOT_CONNECTED),
|
||||
mConnected(false),
|
||||
mInfo(),
|
||||
mRefreshInfo(false),
|
||||
mReadFromMaster(false)
|
||||
{
|
||||
}
|
||||
|
||||
void LLTwitterConnect::openTwitterWeb(std::string url)
|
||||
{
|
||||
// Open the URL in an internal browser window without navigation UI
|
||||
LLFloaterWebContent::Params p;
|
||||
p.url(url);
|
||||
p.show_chrome(true);
|
||||
p.allow_address_entry(false);
|
||||
p.allow_back_forward_navigation(false);
|
||||
p.trusted_content(true);
|
||||
p.clean_browser(true);
|
||||
LLFloater *floater = LLFloaterReg::showInstance("twitter_web", p);
|
||||
//the internal web browser has a bug that prevents it from gaining focus unless a mouse event occurs first (it seems).
|
||||
//So when showing the internal web browser, set focus to it's containing floater "twitter_web". When a mouse event
|
||||
//occurs on the "webbrowser" panel part of the floater, a mouse cursor will properly show and the "webbrowser" will gain focus.
|
||||
//twitter_web floater contains the "webbrowser" panel. JIRA: ACME-744
|
||||
gFocusMgr.setKeyboardFocus( floater );
|
||||
|
||||
//LLUrlAction::openURLExternal(url);
|
||||
}
|
||||
|
||||
std::string LLTwitterConnect::getTwitterConnectURL(const std::string& route, bool include_read_from_master)
|
||||
{
|
||||
std::string url("");
|
||||
LLViewerRegion *regionp = gAgent.getRegion();
|
||||
if (regionp)
|
||||
{
|
||||
//url = "http://pdp15.lindenlab.com/twitter/agent/" + gAgentID.asString(); // TEMPORARY FOR TESTING - CHO
|
||||
url = regionp->getCapability("TwitterConnect");
|
||||
url += route;
|
||||
|
||||
if (include_read_from_master && mReadFromMaster)
|
||||
{
|
||||
url += "?read_from_master=true";
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
void LLTwitterConnect::connectToTwitter(const std::string& request_token, const std::string& oauth_verifier)
|
||||
{
|
||||
LLSD body;
|
||||
if (!request_token.empty())
|
||||
body["request_token"] = request_token;
|
||||
if (!oauth_verifier.empty())
|
||||
body["oauth_verifier"] = oauth_verifier;
|
||||
|
||||
LLHTTPClient::put(getTwitterConnectURL("/connection"), body, new LLTwitterConnectResponder());
|
||||
}
|
||||
|
||||
void LLTwitterConnect::disconnectFromTwitter()
|
||||
{
|
||||
LLHTTPClient::del(getTwitterConnectURL("/connection"), new LLTwitterDisconnectResponder());
|
||||
}
|
||||
|
||||
void LLTwitterConnect::checkConnectionToTwitter(bool auto_connect)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getTwitterConnectURL("/connection", true), new LLTwitterConnectedResponder(auto_connect),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
|
||||
void LLTwitterConnect::loadTwitterInfo()
|
||||
{
|
||||
if(mRefreshInfo)
|
||||
{
|
||||
const bool follow_redirects = false;
|
||||
const F32 timeout = HTTP_REQUEST_EXPIRY_SECS;
|
||||
LLHTTPClient::get(getTwitterConnectURL("/info", true), new LLTwitterInfoResponder(),
|
||||
LLSD(), timeout, follow_redirects);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterConnect::uploadPhoto(const std::string& image_url, const std::string& status)
|
||||
{
|
||||
LLSD body;
|
||||
body["image"] = image_url;
|
||||
body["status"] = status;
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getTwitterConnectURL("/share/photo", true), body, new LLTwitterShareResponder());
|
||||
}
|
||||
|
||||
void LLTwitterConnect::uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status)
|
||||
{
|
||||
std::string imageFormat;
|
||||
if (dynamic_cast<LLImagePNG*>(image.get()))
|
||||
{
|
||||
imageFormat = "png";
|
||||
}
|
||||
else if (dynamic_cast<LLImageJPEG*>(image.get()))
|
||||
{
|
||||
imageFormat = "jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Image to upload is not a PNG or JPEG" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
// All this code is mostly copied from LLWebProfile::post()
|
||||
const std::string boundary = "----------------------------0123abcdefab";
|
||||
|
||||
LLSD headers;
|
||||
headers["Content-Type"] = "multipart/form-data; boundary=" + boundary;
|
||||
|
||||
std::ostringstream body;
|
||||
|
||||
// *NOTE: The order seems to matter.
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"status\"\r\n\r\n"
|
||||
<< status << "\r\n";
|
||||
|
||||
body << "--" << boundary << "\r\n"
|
||||
<< "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n"
|
||||
<< "Content-Type: image/" << imageFormat << "\r\n\r\n";
|
||||
|
||||
// Insert the image data.
|
||||
// *FIX: Treating this as a string will probably screw it up ...
|
||||
U8* image_data = image->getData();
|
||||
for (S32 i = 0; i < image->getDataSize(); ++i)
|
||||
{
|
||||
body << image_data[i];
|
||||
}
|
||||
|
||||
body << "\r\n--" << boundary << "--\r\n";
|
||||
|
||||
// postRaw() takes ownership of the buffer and releases it later.
|
||||
size_t size = body.str().size();
|
||||
U8 *data = new U8[size];
|
||||
memcpy(data, body.str().data(), size);
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::postRaw(getTwitterConnectURL("/share/photo", true), data, size, new LLTwitterShareResponder(), headers);
|
||||
}
|
||||
|
||||
void LLTwitterConnect::updateStatus(const std::string& status)
|
||||
{
|
||||
LLSD body;
|
||||
body["status"] = status;
|
||||
|
||||
// Note: we can use that route for different publish action. We should be able to use the same responder.
|
||||
LLHTTPClient::post(getTwitterConnectURL("/share/status", true), body, new LLTwitterShareResponder());
|
||||
}
|
||||
|
||||
void LLTwitterConnect::storeInfo(const LLSD& info)
|
||||
{
|
||||
mInfo = info;
|
||||
mRefreshInfo = false;
|
||||
|
||||
sInfoWatcher->post(info);
|
||||
}
|
||||
|
||||
const LLSD& LLTwitterConnect::getInfo() const
|
||||
{
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
void LLTwitterConnect::clearInfo()
|
||||
{
|
||||
mInfo = LLSD();
|
||||
}
|
||||
|
||||
void LLTwitterConnect::setDataDirty()
|
||||
{
|
||||
mRefreshInfo = true;
|
||||
}
|
||||
|
||||
void LLTwitterConnect::setConnectionState(LLTwitterConnect::EConnectionState connection_state)
|
||||
{
|
||||
if(connection_state == TWITTER_CONNECTED)
|
||||
{
|
||||
mReadFromMaster = true;
|
||||
setConnected(true);
|
||||
setDataDirty();
|
||||
}
|
||||
else if(connection_state == TWITTER_NOT_CONNECTED)
|
||||
{
|
||||
setConnected(false);
|
||||
}
|
||||
else if(connection_state == TWITTER_POSTED)
|
||||
{
|
||||
mReadFromMaster = false;
|
||||
}
|
||||
|
||||
if (mConnectionState != connection_state)
|
||||
{
|
||||
// set the connection state before notifying watchers
|
||||
mConnectionState = connection_state;
|
||||
|
||||
LLSD state_info;
|
||||
state_info["enum"] = connection_state;
|
||||
sStateWatcher->post(state_info);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTwitterConnect::setConnected(bool connected)
|
||||
{
|
||||
mConnected = connected;
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* @file lltwitterconnect.h
|
||||
* @author Merov, Cho
|
||||
* @brief Connection to Twitter Service
|
||||
*
|
||||
* $LicenseInfo:firstyear=2013&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2013, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLTWITTERCONNECT_H
|
||||
#define LL_LLTWITTERCONNECT_H
|
||||
|
||||
#include "llsingleton.h"
|
||||
#include "llimage.h"
|
||||
|
||||
class LLEventPump;
|
||||
|
||||
/**
|
||||
* @class LLTwitterConnect
|
||||
*
|
||||
* Manages authentication to, and interaction with, a web service allowing the
|
||||
* the viewer to post status updates and upload photos to Twitter.
|
||||
*/
|
||||
class LLTwitterConnect : public LLSingleton<LLTwitterConnect>
|
||||
{
|
||||
LOG_CLASS(LLTwitterConnect);
|
||||
public:
|
||||
enum EConnectionState
|
||||
{
|
||||
TWITTER_NOT_CONNECTED = 0,
|
||||
TWITTER_CONNECTION_IN_PROGRESS = 1,
|
||||
TWITTER_CONNECTED = 2,
|
||||
TWITTER_CONNECTION_FAILED = 3,
|
||||
TWITTER_POSTING = 4,
|
||||
TWITTER_POSTED = 5,
|
||||
TWITTER_POST_FAILED = 6,
|
||||
TWITTER_DISCONNECTING = 7,
|
||||
TWITTER_DISCONNECT_FAILED = 8
|
||||
};
|
||||
|
||||
void connectToTwitter(const std::string& request_token = "", const std::string& oauth_verifier = ""); // Initiate the complete Twitter connection. Please use checkConnectionToTwitter() in normal use.
|
||||
void disconnectFromTwitter(); // Disconnect from the Twitter service.
|
||||
void checkConnectionToTwitter(bool auto_connect = false); // Check if an access token is available on the Twitter service. If not, call connectToTwitter().
|
||||
|
||||
void loadTwitterInfo();
|
||||
void uploadPhoto(const std::string& image_url, const std::string& status);
|
||||
void uploadPhoto(LLPointer<LLImageFormatted> image, const std::string& status);
|
||||
void updateStatus(const std::string& status);
|
||||
|
||||
void storeInfo(const LLSD& info);
|
||||
const LLSD& getInfo() const;
|
||||
void clearInfo();
|
||||
void setDataDirty();
|
||||
|
||||
void setConnectionState(EConnectionState connection_state);
|
||||
void setConnected(bool connected);
|
||||
bool isConnected() { return mConnected; }
|
||||
bool isTransactionOngoing() { return ((mConnectionState == TWITTER_CONNECTION_IN_PROGRESS) || (mConnectionState == TWITTER_POSTING) || (mConnectionState == TWITTER_DISCONNECTING)); }
|
||||
EConnectionState getConnectionState() { return mConnectionState; }
|
||||
|
||||
void openTwitterWeb(std::string url);
|
||||
|
||||
private:
|
||||
friend class LLSingleton<LLTwitterConnect>;
|
||||
|
||||
LLTwitterConnect();
|
||||
~LLTwitterConnect() {};
|
||||
std::string getTwitterConnectURL(const std::string& route = "", bool include_read_from_master = false);
|
||||
|
||||
EConnectionState mConnectionState;
|
||||
BOOL mConnected;
|
||||
LLSD mInfo;
|
||||
bool mRefreshInfo;
|
||||
bool mReadFromMaster;
|
||||
|
||||
static boost::scoped_ptr<LLEventPump> sStateWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sInfoWatcher;
|
||||
static boost::scoped_ptr<LLEventPump> sContentWatcher;
|
||||
};
|
||||
|
||||
#endif // LL_LLTWITTERCONNECT_H
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
#include "llfloateravatar.h"
|
||||
#include "llfloateravatarpicker.h"
|
||||
#include "llfloateravatartextures.h"
|
||||
#include "llfloaterbigpreview.h"
|
||||
#include "llfloaterbeacons.h"
|
||||
#include "llfloaterbuildoptions.h"
|
||||
#include "llfloaterbulkpermission.h"
|
||||
|
|
@ -61,6 +62,8 @@
|
|||
#include "llfloatereditwater.h"
|
||||
#include "llfloaterenvironmentsettings.h"
|
||||
#include "llfloaterevent.h"
|
||||
#include "llfloaterfacebook.h"
|
||||
#include "llfloaterflickr.h"
|
||||
#include "llfloaterfonttest.h"
|
||||
#include "llfloatergesture.h"
|
||||
#include "llfloatergodtools.h"
|
||||
|
|
@ -104,7 +107,6 @@
|
|||
#include "llfloatersettingsdebug.h"
|
||||
#include "llfloatersidepanelcontainer.h"
|
||||
#include "llfloatersnapshot.h"
|
||||
#include "llfloatersocial.h"
|
||||
#include "llfloatersounddevices.h"
|
||||
#include "llfloaterspellchecksettings.h"
|
||||
#include "llfloatertelehub.h"
|
||||
|
|
@ -116,6 +118,7 @@
|
|||
#include "llfloatertos.h"
|
||||
#include "llfloatertoybox.h"
|
||||
#include "llfloatertranslationsettings.h"
|
||||
#include "llfloatertwitter.h"
|
||||
#include "llfloateruipreview.h"
|
||||
#include "llfloatervoiceeffect.h"
|
||||
#include "llfloaterwebcontent.h"
|
||||
|
|
@ -362,7 +365,6 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
|
||||
LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
|
||||
LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);
|
||||
LLFloaterReg::add("social", "floater_social.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSocial>);
|
||||
LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
|
||||
LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>);
|
||||
LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>);
|
||||
|
|
@ -372,8 +374,16 @@ void LLViewerFloaterReg::registerFloaters()
|
|||
//LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
|
||||
LLFloaterReg::add("my_profile", "floater_my_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
|
||||
LLFloaterReg::add("profile", "floater_web_profile.xml", (LLFloaterBuildFunc)&LLFloaterWebProfile::create);
|
||||
LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
LLFloaterReg::add("how_to", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
|
||||
LLFloaterReg::add("fbc_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
LLFloaterReg::add("flickr_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
LLFloaterReg::add("twitter_web", "floater_fbc_web.xml", (LLFloaterBuildFunc)&LLFloaterWebContent::create);
|
||||
|
||||
LLFloaterReg::add("facebook", "floater_facebook.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFacebook>);
|
||||
LLFloaterReg::add("flickr", "floater_flickr.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFlickr>);
|
||||
LLFloaterReg::add("twitter", "floater_twitter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTwitter>);
|
||||
LLFloaterReg::add("big_preview", "floater_big_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBigPreview>);
|
||||
|
||||
LLFloaterUIPreviewUtil::registerFloater();
|
||||
LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload");
|
||||
|
|
|
|||
|
|
@ -1552,7 +1552,7 @@ void LLViewerMedia::createSpareBrowserMediaSource()
|
|||
// popping up at the moment we start a media plugin.
|
||||
if (!sSpareBrowserMediaSource && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
|
||||
{
|
||||
// The null owner will keep the browser plugin from fully initializing
|
||||
// The null owner will keep the browser plugin from fully initializing
|
||||
// (specifically, it keeps LLPluginClassMedia from negotiating a size change,
|
||||
// which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color)
|
||||
sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType(HTTP_CONTENT_TEXT_HTML, NULL, 0, 0);
|
||||
|
|
@ -1561,7 +1561,7 @@ void LLViewerMedia::createSpareBrowserMediaSource()
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// static
|
||||
LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
|
||||
LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()
|
||||
{
|
||||
LLPluginClassMedia* result = sSpareBrowserMediaSource;
|
||||
sSpareBrowserMediaSource = NULL;
|
||||
|
|
@ -1610,7 +1610,7 @@ std::string LLViewerMedia::getParcelAudioURL()
|
|||
// static
|
||||
void LLViewerMedia::initClass()
|
||||
{
|
||||
gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
|
||||
gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL);
|
||||
sTeleportFinishConnection = LLViewerParcelMgr::getInstance()->
|
||||
setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished));
|
||||
}
|
||||
|
|
@ -1698,7 +1698,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
|
|||
mNavigateSuspendedDeferred(false),
|
||||
mIsUpdated(false),
|
||||
mTrustedBrowser(false),
|
||||
mZoomFactor(1.0)
|
||||
mZoomFactor(1.0),
|
||||
mCleanBrowser(false)
|
||||
{
|
||||
|
||||
// Set up the mute list observer if it hasn't been set up already.
|
||||
|
|
@ -1822,14 +1823,16 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
/*static*/
|
||||
LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target)
|
||||
LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target, bool clean_browser)
|
||||
{
|
||||
std::string plugin_basename = LLMIMETypes::implType(media_type);
|
||||
LLPluginClassMedia* media_source = NULL;
|
||||
|
||||
// HACK: we always try to keep a spare running webkit plugin around to improve launch times.
|
||||
// If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it.
|
||||
if(plugin_basename == "media_plugin_webkit" && !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))
|
||||
// Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others)
|
||||
if ((plugin_basename == "media_plugin_webkit") &&
|
||||
!gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser)
|
||||
{
|
||||
media_source = LLViewerMedia::getSpareBrowserMediaSource();
|
||||
if(media_source)
|
||||
|
|
@ -1841,7 +1844,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
|
|||
return media_source;
|
||||
}
|
||||
}
|
||||
|
||||
if(plugin_basename.empty())
|
||||
{
|
||||
LL_WARNS_ONCE("Media") << "Couldn't find plugin for media type " << media_type << LL_ENDL;
|
||||
|
|
@ -1885,18 +1887,18 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
|
|||
|
||||
// collect 'cookies enabled' setting from prefs and send to embedded browser
|
||||
bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
|
||||
media_source->enable_cookies( cookies_enabled );
|
||||
media_source->enable_cookies( cookies_enabled || clean_browser);
|
||||
|
||||
// collect 'plugins enabled' setting from prefs and send to embedded browser
|
||||
bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
|
||||
media_source->setPluginsEnabled( plugins_enabled );
|
||||
media_source->setPluginsEnabled( plugins_enabled || clean_browser);
|
||||
|
||||
// collect 'javascript enabled' setting from prefs and send to embedded browser
|
||||
bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
|
||||
media_source->setJavascriptEnabled( javascript_enabled );
|
||||
media_source->setJavascriptEnabled( javascript_enabled || clean_browser);
|
||||
|
||||
bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging");
|
||||
media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled );
|
||||
media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser);
|
||||
|
||||
media_source->setTarget(target);
|
||||
|
||||
|
|
@ -1951,7 +1953,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
|
|||
// Save the MIME type that really caused the plugin to load
|
||||
mCurrentMimeType = mMimeType;
|
||||
|
||||
LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget);
|
||||
LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget, mCleanBrowser);
|
||||
|
||||
if (media_source)
|
||||
{
|
||||
|
|
@ -2575,7 +2577,7 @@ void LLViewerMediaImpl::unload()
|
|||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
|
||||
void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request, bool clean_browser)
|
||||
{
|
||||
cancelMimeTypeProbe();
|
||||
|
||||
|
|
@ -2588,6 +2590,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
|
|||
// Always set the current URL and MIME type.
|
||||
mMediaURL = url;
|
||||
mMimeType = mime_type;
|
||||
mCleanBrowser = clean_browser;
|
||||
|
||||
// Clear the current media URL, since it will no longer be correct.
|
||||
mCurrentMediaURL.clear();
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ public:
|
|||
void navigateReload();
|
||||
void navigateHome();
|
||||
void unload();
|
||||
void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false);
|
||||
void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false);
|
||||
void navigateInternal();
|
||||
void navigateStop();
|
||||
bool handleKeyHere(KEY key, MASK mask);
|
||||
|
|
@ -289,7 +289,7 @@ public:
|
|||
void setTarget(const std::string& target) { mTarget = target; }
|
||||
|
||||
// utility function to create a ready-to-use media instance from a desired media type.
|
||||
static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null);
|
||||
static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null, bool clean_browser = false);
|
||||
|
||||
// Internally set our desired browser user agent string, including
|
||||
// the Second Life version and skin name. Used because we can
|
||||
|
|
@ -464,6 +464,7 @@ private:
|
|||
bool mTrustedBrowser;
|
||||
std::string mTarget;
|
||||
LLNotificationPtr mNotification;
|
||||
bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled
|
||||
|
||||
private:
|
||||
BOOL mIsUpdated ;
|
||||
|
|
|
|||
|
|
@ -257,7 +257,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
|
|||
#endif
|
||||
case LLFilePicker::FFLOAD_XML:
|
||||
return XML_EXTENSIONS;
|
||||
case LLFilePicker::FFLOAD_ALL:
|
||||
case LLFilePicker::FFLOAD_ALL:
|
||||
case LLFilePicker::FFLOAD_EXE:
|
||||
return ALL_FILE_EXTENSIONS;
|
||||
#endif
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -2862,7 +2862,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
|
|||
capabilityNames.append("EstateChangeInfo");
|
||||
capabilityNames.append("EventQueueGet");
|
||||
capabilityNames.append("FacebookConnect");
|
||||
//capabilityNames.append("FacebookRedirect");
|
||||
capabilityNames.append("FlickrConnect");
|
||||
capabilityNames.append("TwitterConnect");
|
||||
|
||||
if (gSavedSettings.getBOOL("UseHTTPInventory"))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ with the same filename but different name
|
|||
<texture name="Command_Chat_Icon" file_name="toolbar_icons/chat.png" preload="true" />
|
||||
<texture name="Command_Compass_Icon" file_name="toolbar_icons/land.png" preload="true" />
|
||||
<texture name="Command_Destinations_Icon" file_name="toolbar_icons/destinations.png" preload="true" />
|
||||
<texture name="Command_Facebook_Icon" file_name="toolbar_icons/facebook.png" preload="true" />
|
||||
<texture name="Command_Flickr_Icon" file_name="toolbar_icons/flickr.png" preload="true" />
|
||||
<texture name="Command_Gestures_Icon" file_name="toolbar_icons/gestures.png" preload="true" />
|
||||
<texture name="Command_HowTo_Icon" file_name="toolbar_icons/howto.png" preload="true" />
|
||||
<texture name="Command_Inventory_Icon" file_name="toolbar_icons/inventory.png" preload="true" />
|
||||
|
|
@ -153,9 +155,9 @@ with the same filename but different name
|
|||
<texture name="Command_Preferences_Icon" file_name="toolbar_icons/preferences.png" preload="true" />
|
||||
<texture name="Command_Profile_Icon" file_name="toolbar_icons/profile.png" preload="true" />
|
||||
<texture name="Command_Search_Icon" file_name="toolbar_icons/search.png" preload="true" />
|
||||
<texture name="Command_Social_Icon" file_name="toolbar_icons/facebook.png" preload="true" />
|
||||
<texture name="Command_Snapshot_Icon" file_name="toolbar_icons/snapshot.png" preload="true" />
|
||||
<texture name="Command_Speak_Icon" file_name="toolbar_icons/speak.png" preload="true" />
|
||||
<texture name="Command_Twitter_Icon" file_name="toolbar_icons/twitter.png" preload="true" />
|
||||
<texture name="Command_View_Icon" file_name="toolbar_icons/view.png" preload="true" />
|
||||
<texture name="Command_Voice_Icon" file_name="toolbar_icons/nearbyvoice.png" preload="true" />
|
||||
<texture name="Caret_Bottom_Icon" file_name="toolbar_icons/caret_bottom.png" preload="true" scale.left="1" scale.top="23" scale.right="15" scale.bottom="1" />
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue