//------------------------------------------------------------------------------- // // DoContinue // // If we get here we probably did something wrong. This selector was needed // before advanceState() was in the FilterRecord*. Now that we use advanceState() // there is nothing for us to do but set all the rectangles to 0 and return. // //------------------------------------------------------------------------------- void DoContinue(void) { VRect zeroRect = { 0, 0, 0, 0 }; SetInRect(zeroRect); SetOutRect(zeroRect); SetMaskRect(zeroRect); }
static int16 RunPlugin(const int16 iSelector) { string sError; try { if(gFilterRecord->bigDocumentData != NULL) gFilterRecord->bigDocumentData->PluginUsing32BitCoordinates = true; switch(iSelector) { case filterSelectorParameters: break; case filterSelectorPrepare: break; case filterSelectorStart: { Run(); printf("UI shutdown\n"); break; } case filterSelectorContinue: { VRect zeroRect = { 0, 0, 0, 0 }; SetInRect(gFilterRecord, zeroRect); SetOutRect(gFilterRecord, zeroRect); SetMaskRect(gFilterRecord, zeroRect); break; } case filterSelectorFinish: break; } } catch(const std::bad_alloc &) { return memFullErr; } catch(const PhotoshopErrorException &e) { return e.m_iErr; } catch(const exception &e) { /* Don't let any exceptions propagate back into Photoshop. */ sError = e.what(); } catch(...) { sError = "Unknown exception"; } if(sError.empty()) return noErr; PlatformData *pPlatform = (PlatformData *) gFilterRecord->platformData; HWND hWnd = (HWND) pPlatform->hwnd; MessageBox(hWnd, sError.c_str(), plugInName, MB_OK); /* Is it OK to return userCanceledErr for a non-cancellation error? The only * difference seems to be that this doesn't display a "couldn't be completed because * of a program error" dialog, which is what we want since we already displayed * the error. */ return userCanceledErr; }
void DoContinue(void) { VRect outRect = { 0, 0, 0, 0}; SetOutRect(outRect); }
void DoStart(void) { // initialize the scene PI3DScene *theScene=PI3DCreateScene(NULL); char currentMaterial[MAX_LINE]; PI3DMesh *mesh; PI3DMaterial *material; int32 currentMaterialID; //create the default material - required strncpy(currentMaterial, "__PS_CS3_3D_Default", MAX_LINE-1); currentMaterial[MAX_LINE-1] = '\0'; currentMaterialID = 0; material = PI3DUpdateMaterials(theScene, currentMaterial, 0); material->diffuse.red = 1.0; material->diffuse.green = 1.0; material->diffuse.blue = 1.0; //Create a second material with the 2 maps attached strncpy(currentMaterial, "MyMaterial", MAX_LINE-1); currentMaterial[MAX_LINE-1] = '\0'; currentMaterialID = 1; material = PI3DUpdateMaterials(theScene, currentMaterial, 0); material->diffuse.red = 0.8; material->diffuse.green = 0.8; material->diffuse.blue = 0.8; material->ambient.red = 0.8; material->ambient.green = 0.8; material->ambient.blue = 0.8; material->specular.red = 0.6; material->specular.green = 0.6; material->specular.blue = 0.6; strncpy(material->maps[PI3DDiffuseMap].map, "Diffuse.png", 2047); material->maps[PI3DDiffuseMap].map[2047] = '\0'; material->maps[PI3DDiffuseMap].strength=1.0f; material->maps[PI3DDiffuseMap].flags=(PI3DTextureMapFlags)0; strncpy(material->maps[PI3DBumpMap].map, "Bump.png", 2047); material->maps[PI3DBumpMap].map[2047] = '\0'; material->maps[PI3DBumpMap].strength=1.0f; material->maps[PI3DBumpMap].flags=(PI3DTextureMapFlags)0; //Create an empty mesh and add to list mesh = PI3DCreateMesh((char*)"", 0, 0, 0, 0, 0, 0); PI3DListAdd((PI3DList **)&theScene->meshList, reinterpret_cast<PI3DList *>(mesh)); //Get things ready to cycle through the pixels int16 tileHeight = gFilterRecord->outTileHeight; int16 tileWidth = gFilterRecord->outTileWidth; if (tileWidth == 0 || tileHeight == 0 || gFilterRecord->advanceState == NULL) { *gResult = filterBadParameters; return; } VRect outRect = GetOutRect(); VRect filterRect = GetFilterRect(); int32 imageVert = filterRect.bottom - filterRect.top; int32 imageHor = filterRect.right - filterRect.left; uint32 tilesVert = (tileHeight - 1 + imageVert) / tileHeight; uint32 tilesHoriz = (tileWidth - 1 + imageHor) / tileWidth; int16 layerPlanes = 1; if (gFilterRecord->filterCase > 2) layerPlanes = gFilterRecord->outLayerPlanes; else layerPlanes = gFilterRecord->planes; int32 progress_total = layerPlanes * tilesVert; int32 progress_complete = 0; //Allocate the space for the vertices and uvs of the mesh mesh->vertices=imageVert*imageHor; mesh->vertex = (PI3DVector *)PI3DMemoryAlloc(sizeof(PI3DVector) * mesh->vertices); mesh->textures=imageVert*imageHor; mesh->texture = (PI3DPoint *)PI3DMemoryAlloc(sizeof(PI3DPoint) * mesh->textures); mesh->faces=(imageVert-1)*(imageHor-1); mesh->face = (PI3DFace *)PI3DMemoryAlloc(sizeof(PI3DFace) * mesh->faces); mesh->smoothingGroupPresent = true; //We'll just grab the red channel for now int16 planeCount = 0; //for(int16 planeCount = 0; planeCount < layerPlanes; planeCount++) { gFilterRecord->outLoPlane = planeCount; gFilterRecord->outHiPlane = planeCount; for(uint16 vertTile = 0; vertTile < tilesVert; vertTile++) { for(uint16 horizTile = 0; horizTile < tilesHoriz; horizTile++) { outRect.top = filterRect.top + ( vertTile * tileHeight ); outRect.left = filterRect.left + ( horizTile * tileWidth ); outRect.bottom = outRect.top + tileHeight; outRect.right = outRect.left + tileWidth; if (outRect.bottom > filterRect.bottom) outRect.bottom = filterRect.bottom; if (outRect.right > filterRect.right) outRect.right = filterRect.right; SetOutRect(outRect); *gResult = gFilterRecord->advanceState(); if (*gResult != kNoErr) return; outRect = GetOutRect(); uint8 * smallPixel = static_cast<uint8 *>(gFilterRecord->outData); uint16 * largePixel = static_cast<uint16 *>(gFilterRecord->outData); uint32 rectHeight = outRect.bottom - outRect.top; uint32 rectWidth = outRect.right - outRect.left; for(uint32 pixelY = 0; pixelY < rectHeight; pixelY++) { for(uint32 pixelX = 0; pixelX < rectWidth; pixelX++) { uint32 x = outRect.left + pixelX; uint32 y = outRect.top + pixelY; uint32 vertexIndex = x + imageHor*y; uint16 height=0; if (gFilterRecord->depth == 8 && *smallPixel) height=*smallPixel; if (gFilterRecord->depth == 16 && *largePixel) height=*largePixel; //Calculate each vertex based on the pixel value mesh->vertex[vertexIndex][0]=imageHor-x; mesh->vertex[vertexIndex][1]=height; mesh->vertex[vertexIndex][2]=imageVert-y; //Calculate each texture coordinate based on the pixel value mesh->texture[vertexIndex][0]=((nativeFloat)x)/((nativeFloat)imageHor); mesh->texture[vertexIndex][1]=((nativeFloat)(imageVert-y))/((nativeFloat)imageVert); largePixel++; smallPixel++; } smallPixel += gFilterRecord->outRowBytes - rectWidth; largePixel += gFilterRecord->outRowBytes / 2 - rectWidth; } } gFilterRecord->progressProc(++progress_complete, progress_total); if (gFilterRecord->abortProc()) { *gResult = userCanceledErr; goto done; } } } done: outRect.top = 0; outRect.left = 0; outRect.bottom = 0; outRect.right = 0; SetOutRect(outRect); //Cycle back through and create faces to map to the vertices and uvs we made int32 x1,y1,faceIndex=0; for(y1=filterRect.top; y1<filterRect.bottom-1;y1++) { int32 topLeft=y1*imageHor; int32 topRight=1+y1*imageHor; int32 bottomLeft=(y1+1)*imageHor; int32 bottomRight=1+(y1+1)*imageHor; for(x1=filterRect.left; x1<filterRect.right-1;x1++) { //Only add a face if there is a non-black value in one of the 4 corners - this is how holes are made if(mesh->vertex[topLeft][1] || mesh->vertex[topRight][1] || mesh->vertex[bottomLeft][1] || mesh->vertex[bottomRight][1]) { int32 nPoints = 4; PI3DFace f; memset(&f, 0, sizeof(f)); f.points = (int32 *)PI3DMemoryAlloc(sizeof(int32) * nPoints); f.normals = (int32 *)PI3DMemoryAlloc(sizeof(int32) * nPoints); f.textures = (int32 *)PI3DMemoryAlloc(sizeof(int32) * nPoints); f.colors = (int32 *)PI3DMemoryAlloc(sizeof(int32) * nPoints); f.flags = 0x57; if (f.points == NULL || f.normals == NULL || f.textures == NULL || f.colors == NULL) break; f.smoothing = 1; f.material = currentMaterialID; f.numPoints = nPoints; f.points[0]=topLeft; f.normals[0]=topLeft; f.textures[0]=topLeft; f.colors[0]=topLeft; f.points[1]=topRight; f.normals[1]=topRight; f.textures[1]=topRight; f.colors[1]=topRight; f.points[2]=bottomRight; f.normals[2]=bottomRight; f.textures[2]=bottomRight; f.colors[2]=bottomRight; f.points[3]=bottomLeft; f.normals[3]=bottomLeft; f.textures[3]=bottomLeft; f.colors[3]=bottomLeft; mesh->face[faceIndex++]=f; } topLeft++; bottomRight++; bottomLeft++; topRight++; } } //Reset the # of faces to match how many we actually added mesh->faces=faceIndex; if(theScene) { //Fill in scene PI3DDescriptorProcs descriptorProcs; descriptorProcs.actionDescriptorProcs=NULL; descriptorProcs.actionListProcs=NULL; descriptorProcs.actionControlProcs=NULL; descriptorProcs.zStringProcs=NULL; int32 error = gFilterRecord->sSPBasic->AcquireSuite(kPSActionDescriptorSuite, kPSActionDescriptorSuiteVersion, (const void**)&descriptorProcs.actionDescriptorProcs); if(!error) error = gFilterRecord->sSPBasic->AcquireSuite(kPSActionListSuite, kPSActionListSuiteVersion, (const void**)&descriptorProcs.actionListProcs); if(!error) error = gFilterRecord->sSPBasic->AcquireSuite(kPSBasicActionControlSuite, kPSBasicActionControlSuitePrevVersion, (const void**)&descriptorProcs.actionControlProcs); if(!error) error = gFilterRecord->sSPBasic->AcquireSuite(kASZStringSuite, kASZStringSuiteVersion1, (const void**)&descriptorProcs.zStringProcs); PIActionDescriptor theLayerDescriptor=NULL; if(!error) { descriptorProcs.actionDescriptorProcs->Make(&theLayerDescriptor); if(theLayerDescriptor) { PI3DLayer * theLayer = new PI3DLayer; if (theLayer == NULL) return; VPoint docSize; docSize.h=gFilterRecord->imageSize.h; docSize.v=gFilterRecord->imageSize.v; //Get the 3D layer set up PI3DInitialize3DLayer(theLayer,&docSize); //Hand it the scene we created theLayer->currentScene=theScene; //Fill in current camera and object position and the textures //Set up an orthographic camera to fit the object exactly in the view //This first section is for the View menu in the 3D tool theLayer->stateList.length=1; theLayer->stateList.positionNames=(uint16**)PI3DMemoryAlloc(theLayer->stateList.length * sizeof(uint16*)); theLayer->stateList.positionNames[0] = (uint16*)PI3DMemoryAlloc(256 * sizeof(uint16)); PI3DStringCopyC16(theLayer->stateList.positionNames[0],(const char *)"Test Camera"); theLayer->stateList.viewStates=(RenderState*)PI3DMemoryAlloc(theLayer->stateList.length * sizeof(RenderState)); memset(&theLayer->stateList.viewStates[0],0,sizeof(RenderState)); if(gFilterRecord->depth == 8) theLayer->stateList.viewStates[0].currentCameraPosition.y = 400; else theLayer->stateList.viewStates[0].currentCameraPosition.y = 100000; theLayer->stateList.viewStates[0].currentOrthoScale=imageVert; theLayer->stateList.viewStates[0].currentOrthographic=true; theLayer->stateList.viewStates[0].currentCameraPosition.xAngle=-90; theLayer->stateList.viewStates[0].currentFieldOfView=42.0; theLayer->stateIndex=8; //This sets the current view to be this camera theLayer->currentRenderState.currentOrthoScale=theLayer->stateList.viewStates[0].currentOrthoScale; theLayer->currentRenderState.currentOrthographic=theLayer->stateList.viewStates[0].currentOrthographic; theLayer->currentRenderState.currentCameraPosition=theLayer->stateList.viewStates[0].currentCameraPosition; theLayer->currentRenderState.currentFieldOfView=theLayer->stateList.viewStates[0].currentFieldOfView; //Add in some textures theLayer->texturesExternal=true; //Textures are external to the file theLayer->texturesEnabled=true; //The master eyeball theLayer->textureList.length=2; //The individual eyyeballs theLayer->textureEnabled = (Boolean*)PI3DMemoryAlloc(theLayer->textureList.length * sizeof(Boolean)); theLayer->textureEnabled[0]=true; theLayer->textureEnabled[1]=true; //The type of each texture - Note that bump maps disable the Cross Section tool theLayer->textureList.textureType = (uint32*)PI3DMemoryAlloc(theLayer->textureList.length * sizeof(uint32)); theLayer->textureList.textureType[0]=k3DMapTypeTexture; theLayer->textureList.textureType[1]=k3DMapTypeBump; //We need to set a path for the scene so that PS knows where to look for textures theLayer->scenePath = (uint16*)PI3DMemoryAlloc(256 * sizeof(uint16)); GetTempFolderPath( theLayer->scenePath, 256 * sizeof(uint16) - 1); StringAppend3D(theLayer->scenePath,(char*)"dummy.obj", 256 * sizeof(uint16)); //Give the paths to the textures //In this case we're just going to give paths to nothing //This will create empty textures that users can fill in later //Note that whatever path you put in for texturePaths, that file will get removed as //it is assumed to be a temp file. So, you probably want point it at a bogus file. theLayer->textureList.textureNames = (uint16**)PI3DMemoryAlloc(theLayer->textureList.length * sizeof(uint16*)); theLayer->textureList.texturePaths =(uint16**) PI3DMemoryAlloc(theLayer->textureList.length * sizeof(uint16*)); theLayer->textureList.texturePaths[0] = (uint16*)PI3DMemoryAlloc(256 * sizeof(uint16)); theLayer->textureList.textureNames[0] = (uint16*)PI3DMemoryAlloc(256 * sizeof(uint16)); theLayer->textureList.texturePaths[0][0]=0; GetTempFolderPath( theLayer->textureList.textureNames[0], 256 * sizeof(uint16) - 1); StringAppend3D(theLayer->textureList.textureNames[0],(char*)"Diffuse.png", 256 * sizeof(uint16)); StringAppend3D(theLayer->textureList.texturePaths[0],(char*)"Diffuse.png", 256 * sizeof(uint16)); theLayer->textureList.texturePaths[1] = (uint16*)PI3DMemoryAlloc(256 * sizeof(uint16)); theLayer->textureList.textureNames[1] = (uint16*)PI3DMemoryAlloc(256 * sizeof(uint16)); theLayer->textureList.texturePaths[1][0]=0; GetTempFolderPath( theLayer->textureList.textureNames[1], 256 * sizeof(uint16) - 1); StringAppend3D(theLayer->textureList.texturePaths[1],(char*)"Bump.png", 256 * sizeof(uint16)); StringAppend3D(theLayer->textureList.textureNames[1],(char*)"Bump.png", 256 * sizeof(uint16)); //Convert the entire layer data structure into a descriptor for Photoshop PI3DMakeLayerDescriptor(&descriptorProcs, theLayer, theLayerDescriptor); //Clean up behind us theLayer->currentScene=NULL; PI3DKill3DLayer(theLayer); delete theLayer; } } //Clean up behind us if(theScene) PI3DKillScene(theScene); //Convert theLayerDescriptor to a handle and free the descriptor //When PS sees this descriptor handle it creates a new 3D layer with that data in it if(theLayerDescriptor) { descriptorProcs.actionDescriptorProcs->AsHandle(theLayerDescriptor, &gFilterRecord->output3DScene->descriptor); descriptorProcs.actionDescriptorProcs->Free(theLayerDescriptor); } } }
//------------------------------------------------------------------------------- // // DoFilter // // Randomly change the pixel values based on the parameters the user gave us from // our dialog box or scripting. We do this a tile at a time making sure the rect. // we ask for is in the bounds of the filterRect. // //------------------------------------------------------------------------------- void DoFilter(void) { // make the random number generated trully random srand((unsigned)time(NULL)); int32 tileHeight = gFilterRecord->outTileHeight; int32 tileWidth = gFilterRecord->outTileWidth; if (tileWidth == 0 || tileHeight == 0) { *gResult = filterBadParameters; return; } VRect filterRect = GetFilterRect(); int32 rectWidth = filterRect.right - filterRect.left; int32 rectHeight = filterRect.bottom - filterRect.top; CreateDissolveBuffer(tileWidth, tileHeight); // round up to the nearest horizontal and vertical tile count int32 tilesVert = (tileHeight - 1 + rectHeight) / tileHeight; int32 tilesHoriz = (tileWidth - 1 + rectWidth) / tileWidth; // Fixed numbers are 16.16 values // the first 16 bits represent the whole number // the last 16 bits represent the fraction gFilterRecord->inputRate = (int32)1 << 16; gFilterRecord->maskRate = (int32)1 << 16; // variables for the progress bar, our plug in is so fast // we probably don't need these int32 progressTotal = tilesVert * tilesHoriz; int32 progressDone = 0; // loop through each tile makeing sure we don't go over the bounds // of the rectHeight or rectWidth for (int32 vertTile = 0; vertTile < tilesVert; vertTile++) { for (int32 horizTile = 0; horizTile < tilesHoriz; horizTile++) { UpdateDissolveBuffer(tileWidth, tileHeight); VRect filterRect = GetFilterRect(); VRect inRect = GetInRect(); inRect.top = vertTile * tileHeight + filterRect.top; inRect.left = horizTile * tileWidth + filterRect.left; inRect.bottom = inRect.top + tileHeight; inRect.right = inRect.left + tileWidth; if (inRect.bottom > rectHeight) inRect.bottom = rectHeight; if (inRect.right > rectWidth) inRect.right = rectWidth; SetInRect(inRect); // duplicate what's in the inData with the outData SetOutRect(inRect); // get the maskRect if the user has given us a selection if (gFilterRecord->haveMask) { SetMaskRect(inRect); } for (int16 plane = 0; plane < gFilterRecord->planes; plane++) { // we want one plane at a time, small memory foot print is good gFilterRecord->outLoPlane = gFilterRecord->inLoPlane = plane; gFilterRecord->outHiPlane = gFilterRecord->inHiPlane = plane; // update the gFilterRecord with our latest request *gResult = gFilterRecord->advanceState(); if (*gResult != noErr) return; // muck with the pixels in the outData buffer uint8 color = 255; int16 expectedPlanes = CSPlanesFromMode(gFilterRecord->imageMode, 0); if (plane < expectedPlanes) color = gData->color[plane]; DissolveRectangle(gFilterRecord->outData, gFilterRecord->outRowBytes, gFilterRecord->maskData, gFilterRecord->maskRowBytes, GetOutRect(), color, gFilterRecord->depth); } // uh, update the progress bar gFilterRecord->progressProc(++progressDone, progressTotal); // see if the user is impatient or didn't mean to do that if (gFilterRecord->abortProc()) { *gResult = userCanceledErr; return; } } } DeleteDissolveBuffer(); }