Merge pull request #874 from trevorsandy/BLENDER_AND_POVRAY_LIGHTS

Blender and POVRay Lights
This commit is contained in:
Leonardo Zide 2023-12-23 11:36:38 -08:00 committed by GitHub
commit 0da3def563
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 3533 additions and 1280 deletions

View file

@ -142,20 +142,9 @@ void lcCamera::SaveLDraw(QTextStream& Stream) const
Stream << QLatin1String("0 !LEOCAD CAMERA FOV ") << m_fovy << QLatin1String(" ZNEAR ") << m_zNear << QLatin1String(" ZFAR ") << m_zFar << LineEnding;
if (mPositionKeys.GetSize() > 1)
mPositionKeys.SaveKeysLDraw(Stream, "CAMERA POSITION_KEY ");
else
Stream << QLatin1String("0 !LEOCAD CAMERA POSITION ") << mPosition[0] << ' ' << mPosition[1] << ' ' << mPosition[2] << LineEnding;
if (mTargetPositionKeys.GetSize() > 1)
mTargetPositionKeys.SaveKeysLDraw(Stream, "CAMERA TARGET_POSITION_KEY ");
else
Stream << QLatin1String("0 !LEOCAD CAMERA TARGET_POSITION ") << mTargetPosition[0] << ' ' << mTargetPosition[1] << ' ' << mTargetPosition[2] << LineEnding;
if (mUpVectorKeys.GetSize() > 1)
mUpVectorKeys.SaveKeysLDraw(Stream, "CAMERA UP_VECTOR_KEY ");
else
Stream << QLatin1String("0 !LEOCAD CAMERA UP_VECTOR ") << mUpVector[0] << ' ' << mUpVector[1] << ' ' << mUpVector[2] << LineEnding;
SaveAttribute(Stream, mPosition, mPositionKeys, "CAMERA", "POSITION");
SaveAttribute(Stream, mTargetPosition, mTargetPositionKeys, "CAMERA", "TARGET_POSITION");
SaveAttribute(Stream, mUpVector, mUpVectorKeys, "CAMERA", "UP_VECTOR");
Stream << QLatin1String("0 !LEOCAD CAMERA ");
@ -176,7 +165,7 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream)
Stream >> Token;
if (Token == QLatin1String("HIDDEN"))
SetHidden(true);
SetHidden(true);
else if (Token == QLatin1String("ORTHOGRAPHIC"))
SetOrtho(true);
else if (Token == QLatin1String("FOV"))
@ -185,27 +174,12 @@ bool lcCamera::ParseLDrawLine(QTextStream& Stream)
Stream >> m_zNear;
else if (Token == QLatin1String("ZFAR"))
Stream >> m_zFar;
else if (Token == QLatin1String("POSITION"))
{
Stream >> mPosition[0] >> mPosition[1] >> mPosition[2];
mPositionKeys.ChangeKey(mPosition, 1, true);
}
else if (Token == QLatin1String("TARGET_POSITION"))
{
Stream >> mTargetPosition[0] >> mTargetPosition[1] >> mTargetPosition[2];
mTargetPositionKeys.ChangeKey(mTargetPosition, 1, true);
}
else if (Token == QLatin1String("UP_VECTOR"))
{
Stream >> mUpVector[0] >> mUpVector[1] >> mUpVector[2];
mUpVectorKeys.ChangeKey(mUpVector, 1, true);
}
else if (Token == QLatin1String("POSITION_KEY"))
mPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("TARGET_POSITION_KEY"))
mTargetPositionKeys.LoadKeysLDraw(Stream);
else if (Token == QLatin1String("UP_VECTOR_KEY"))
mUpVectorKeys.LoadKeysLDraw(Stream);
else if (LoadAttribute(Stream, Token, mPosition, mPositionKeys, "POSITION"))
continue;
else if (LoadAttribute(Stream, Token, mTargetPosition, mTargetPositionKeys, "TARGET_POSITION"))
continue;
else if (LoadAttribute(Stream, Token, mUpVector, mUpVectorKeys, "UP_VECTOR"))
continue;
else if (Token == QLatin1String("NAME"))
{
mName = Stream.readAll().trimmed();

View file

@ -202,7 +202,7 @@ public:
quint32 GetAllowedTransforms() const override
{
return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z;
return LC_OBJECT_TRANSFORM_MOVE_XYZ;
}
lcVector3 GetSectionPosition(quint32 Section) const override

View file

@ -123,7 +123,7 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettings [N
/* 2 LBL_BEVEL_EDGES */ {"beveledges", "1", QObject::tr("Bevel Edges"), QObject::tr("Adds a Bevel modifier for rounding off sharp edges")},
/* 3 LBL_BLENDFILE_TRUSTED */ {"blendfiletrusted", "0", QObject::tr("Trusted Blend File"), QObject::tr("Specify whether to treat the .blend file as being loaded from a trusted source")},
/* 4 LBL_CROP_IMAGE */ {"cropimage", "0", QObject::tr("Crop Image"), QObject::tr("Crop the image border at opaque content. Requires transparent background set to True")},
/* 5 LBL_CURVED_WALLS */ {"curvedwalls", "1", QObject::tr("Curved Walls"), QObject::tr("Makes surfaces look slightly concave")},
/* 5 LBL_CURVED_WALLS */ {"curvedwalls", "1", QObject::tr("Curved Walls"), QObject::tr("Makes surfaces look slightly concave, for interesting reflections")},
/* 6 LBL_FLATTEN_HIERARCHY */ {"flattenhierarchy", "0", QObject::tr("Flatten Hierarchy"), QObject::tr("In Scene Outline, all parts are placed directly below the root - there's no tree of submodels")},
/* 7 LBL_IMPORT_CAMERAS */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)},
/* 8 LBL_IMPORT_LIGHTS */ {"importlights", "1", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)},
@ -147,12 +147,12 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettings [N
/*26 LBL_VERBOSE */ {"verbose", "1", QObject::tr("Verbose output"), QObject::tr("Output all messages while working, else only show warnings and errors")},
/*27/0 LBL_BEVEL_WIDTH */ {"bevelwidth", "0.5", QObject::tr("Bevel Width"), QObject::tr("Width of the bevelled edges")},
/*28/1 LBL_CAMERA_BORDER_PERCENT */ {"cameraborderpercentage", "5.0", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border around the model in the render")},
/*28/1 LBL_CAMERA_BORDER_PERCENT */ {"cameraborderpercentage", "5.0", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border leeway around the model in the rendered image")},
/*29/2 LBL_DEFAULT_COLOUR */ {"defaultcolour", "16", QObject::tr("Default Colour"), QObject::tr("Sets the default part colour using LDraw colour code")},
/*20/3 LBL_GAPS_SIZE */ {"gapwidth", "0.01", QObject::tr("Gap Width"), QObject::tr("Amount of gap space between each part")},
/*20/3 LBL_GAPS_SIZE */ {"realgapwidth", "0.0002", QObject::tr("Gap Width"), QObject::tr("Amount of space between each part (default 0.2mm)")},
/*31/4 LBL_IMAGE_WIDTH */ {"resolutionwidth", "800", QObject::tr("Image Width"), QObject::tr("Sets the rendered image width in pixels - from current step image, label shows config setting.")},
/*32/5 LBL_IMAGE_HEIGHT */ {"resolutionheight", "600", QObject::tr("Image Height"), QObject::tr("Sets the rendered image height in pixels - from current step image, label shows config setting.")},
/*33/6 LBL_IMAGE_SCALE */ {"scale", "0.02", QObject::tr("Image Scale"), QObject::tr("Sets the imported model scale (between .01 and 1.0). Scale is 1.0 and is huge and unwieldy in the viewport")},
/*33/6 LBL_IMAGE_SCALE */ {"realscale", "1.0", QObject::tr("Image Scale"), QObject::tr("Sets a scale for the model (1.0 = real life scale)")},
/*34/6 LBL_RENDER_PERCENTAGE */ {"renderpercentage", "100", QObject::tr("Render Percentage"), QObject::tr("Sets the rendered image percentage scale for its pixel resolution - updated from current step, label shows config setting.")},
/*35/0 LBL_COLOUR_SCHEME */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")},
@ -183,29 +183,33 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM
/* 00 LBL_ADD_ENVIRONMENT_MM */ {"addenvironment", "1", QObject::tr("Add Environment"), QObject::tr("Adds a ground plane and environment texture")},
/* 01 LBL_BEVEL_EDGES_MM */ {"beveledges", "0", QObject::tr("Bevel Edgest"), QObject::tr("Bevel edges. Can cause some parts to render incorrectly")},
/* 02 LBL_BLEND_FILE_TRUSTED_MM */ {"blendfiletrusted", "0", QObject::tr("Trusted Blend File"), QObject::tr("Specify whether to treat the .blend file as being loaded from a trusted source")},
/* 03 LBL_CROP_IMAGE_MM */ {"cropimage", "0", QObject::tr("Crop Image"), QObject::tr("Crop the image border at opaque content. Requires transparent background set to True")},
/* 04 LBL_DISPLAY_LOGO */ {"displaylogo", "1", QObject::tr("Display Logo"), QObject::tr("Display the logo on the stud")},
/* 05 LBL_IMPORT_CAMERAS_MM */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)},
/* 06 LBL_IMPORT_EDGES */ {"importedges", "0", QObject::tr("Import Edges"), QObject::tr("Import LDraw edges as edges")},
/* 07 LBL_IMPORT_LIGHTS_MM */ {"importlights", "0", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)},
/* 08 LBL_KEEP_ASPECT_RATIO_MM */ {"keepaspectratio", "1", QObject::tr("Keep Aspect Ratio"), QObject::tr("Maintain the aspect ratio when resizing the output image - this attribute is not passed to Blender")},
/* 09 LBL_MAKE_GAPS */ {"makegaps", "1", QObject::tr("Make Gaps"), QObject::tr("Make small gaps between bricks. A small gap is more realistic")},
/* 10 LBL_META_BFC */ {"metabfc", "1", QObject::tr("BFC"), QObject::tr("Process LDraw Back Face Culling meta commands")},
/* 11 LBL_META_CLEAR */ {"metaclear", "0", QObject::tr("CLEAR Command"), QObject::tr("Hides all parts in the timeline up to where this command is encountered")},
/* 12 LBL_META_GROUP */ {"metagroup", "1", QObject::tr("GROUP Command"), QObject::tr("Process GROUP meta commands")},
/* 13 LBL_META_PAUSE */ {"metapause", "0", QObject::tr("PAUSE Command"), QObject::tr("Not implemented")},
/* 14 LBL_META_PRINT_WRITE */ {"metaprintwrite", "0", QObject::tr("PRINT/WRITE Command"), QObject::tr("Prints PRINT/WRITE META commands to the system console.")},
/* 15 LBL_META_SAVE */ {"metasave", "0", QObject::tr("SAVE Command"), QObject::tr("Not implemented")},
/* 16 LBL_META_STEP */ {"metastep", "0", QObject::tr("STEP Command"), QObject::tr("Adds a keyframe that shows the part at the moment in the timeline")},
/* 17 LBL_META_STEP_GROUPS */ {"metastepgroups", "0", QObject::tr("STEP Groups"), QObject::tr("Create collection for individual steps")},
/* 18 LBL_META_TEXMAP */ {"metatexmap", "1", QObject::tr("TEXMAP and DATA Command"), QObject::tr("Process TEXMAP and DATA meta commands")},
/* 19 LBL_NO_STUDS */ {"nostuds", "0", QObject::tr("No Studs"), QObject::tr("Don't import studs")},
/* 20 LBL_OVERWRITE_IMAGE_MM */ {"overwriteimage", "1", QObject::tr("Overwrite Image"), QObject::tr("Specify whether to overwrite an existing rendered image file")},
/* 21 LBL_POSITION_CAMERA_MM */ {"positioncamera", "1", QObject::tr("Position Camera"), QObject::tr("Position the camera to show the whole model")},
/* 22 LBL_PARENT_TO_EMPTY */ {"parenttoempty", "1", QObject::tr("Parent To Empty"), QObject::tr("Parent the model to an empty")},
/* 23 LBL_PREFER_STUDIO */ {"preferstudio", "0", QObject::tr("Prefer Stud.io Library"), QObject::tr("Search for parts in Stud.io library first")},
/* 24 LBL_PREFER_UNOFFICIAL */ {"preferunofficial", "0", QObject::tr("Prefer Unofficial Parts"), QObject::tr("Search for unofficial parts first")},
/* 25 LBL_PRESERVE_HIERARCHY */ {"preservehierarchy", "0", QObject::tr("Preserve File Structure"), QObject::tr("Don't merge the constituent subparts and primitives into the top level part. Some parts may not render properly")},
#ifdef Q_OS_LINUX
/* 03 LBL_CASE_SENSITIVE_FILESYSTEM */ {"casesensitivefilesystem", "1", QObject::tr("Case-sensitive Filesystem"),QObject::tr("Filesystem is case sensitive. Defaults to true on Linux.")},
#else
/* 03 LBL_CASE_SENSITIVE_FILESYSTEM */ {"casesensitivefilesystem", "0", QObject::tr("Case-sensitive Filesystem"),QObject::tr("Filesystem case sensitive defaults to false Windows and MacOS. Set true if LDraw path set to case-sensitive on case-insensitive filesystem.")},
#endif
/* 04 LBL_CROP_IMAGE_MM */ {"cropimage", "0", QObject::tr("Crop Image"), QObject::tr("Crop the image border at opaque content. Requires transparent background set to True")},
/* 05 LBL_DISPLAY_LOGO */ {"displaylogo", "1", QObject::tr("Display Logo"), QObject::tr("Display the logo on the stud")},
/* 06 LBL_IMPORT_CAMERAS_MM */ {"importcameras", "1", QObject::tr("Import Cameras"), QObject::tr("%1 can specify camera definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)},
/* 07 LBL_IMPORT_EDGES */ {"importedges", "0", QObject::tr("Import Edges"), QObject::tr("Import LDraw edges as edges")},
/* 08 LBL_IMPORT_LIGHTS_MM */ {"importlights", "1", QObject::tr("Import Lights"), QObject::tr("%1 can specify point and sunlight definitions within the ldraw data. Choose to load them or ignore them.").arg(LC_PRODUCTNAME_STR)},
/* 09 LBL_KEEP_ASPECT_RATIO_MM */ {"keepaspectratio", "1", QObject::tr("Keep Aspect Ratio"), QObject::tr("Maintain the aspect ratio when resizing the output image - this attribute is not passed to Blender")},
/* 10 LBL_MAKE_GAPS */ {"makegaps", "1", QObject::tr("Make Gaps"), QObject::tr("Make small gaps between bricks. A small gap is more realistic")},
/* 11 LBL_META_BFC */ {"metabfc", "1", QObject::tr("BFC"), QObject::tr("Process LDraw Back Face Culling meta commands")},
/* 12 LBL_META_CLEAR */ {"metaclear", "0", QObject::tr("CLEAR Command"), QObject::tr("Hides all parts in the timeline up to where this command is encountered")},
/* 13 LBL_META_GROUP */ {"metagroup", "1", QObject::tr("GROUP Command"), QObject::tr("Process GROUP meta commands")},
/* 14 LBL_META_PAUSE */ {"metapause", "0", QObject::tr("PAUSE Command"), QObject::tr("Not implemented")},
/* 15 LBL_META_PRINT_WRITE */ {"metaprintwrite", "0", QObject::tr("PRINT/WRITE Command"), QObject::tr("Prints PRINT/WRITE META commands to the system console.")},
/* 16 LBL_META_SAVE */ {"metasave", "0", QObject::tr("SAVE Command"), QObject::tr("Not implemented")},
/* 17 LBL_META_STEP */ {"metastep", "0", QObject::tr("STEP Command"), QObject::tr("Adds a keyframe that shows the part at the moment in the timeline")},
/* 18 LBL_META_STEP_GROUPS */ {"metastepgroups", "0", QObject::tr("STEP Groups"), QObject::tr("Create collection for individual steps")},
/* 19 LBL_META_TEXMAP */ {"metatexmap", "1", QObject::tr("TEXMAP and DATA Command"), QObject::tr("Process TEXMAP and DATA meta commands")},
/* 20 LBL_NO_STUDS */ {"nostuds", "0", QObject::tr("No Studs"), QObject::tr("Don't import studs")},
/* 21 LBL_OVERWRITE_IMAGE_MM */ {"overwriteimage", "1", QObject::tr("Overwrite Image"), QObject::tr("Specify whether to overwrite an existing rendered image file")},
/* 22 LBL_POSITION_CAMERA_MM */ {"positioncamera", "1", QObject::tr("Position Camera"), QObject::tr("Position the camera to show the whole model")},
/* 23 LBL_PARENT_TO_EMPTY */ {"parenttoempty", "1", QObject::tr("Parent To Empty"), QObject::tr("Parent the model to an empty")},
/* 24 LBL_PREFER_STUDIO */ {"preferstudio", "0", QObject::tr("Prefer Stud.io Library"), QObject::tr("Search for parts in Stud.io library first")},
/* 25 LBL_PREFER_UNOFFICIAL */ {"preferunofficial", "0", QObject::tr("Prefer Unofficial Parts"), QObject::tr("Search for unofficial parts first")},
/* 26 LBL_PROFILE */ {"profile", "0", QObject::tr("Profile"), QObject::tr("Profile import performance")},
/* 27 LBL_RECALCULATE_NORMALS */ {"recalculatenormals", "0", QObject::tr("Recalculate Normals"), QObject::tr("Recalculate normals. Not recommended if BFC processing is active")},
/* 28 LBL_REMOVE_DOUBLES_MM */ {"removedoubles", "1", QObject::tr("No Duplicate Vertices"), QObject::tr("Merge vertices that are within a certain distance.")},
@ -215,43 +219,40 @@ lcBlenderPreferences::BlenderSettings lcBlenderPreferences::mDefaultSettingsMM
/* 32 LBL_SET_TIMELINE_MARKERS */ {"settimelinemarkers", "0", QObject::tr("Set Timeline Markers"), QObject::tr("Set timeline markers for meta commands")},
/* 33 LBL_SHADE_SMOOTH */ {"shadesmooth", "1", QObject::tr("Shade Smooth"), QObject::tr("Use flat or smooth shading for part faces")},
/* 34 LBL_TRANSPARENT_BACKGROUND_MM */ {"transparentbackground", "0", QObject::tr("Transparent Background"), QObject::tr("Specify whether to render a background")},
/* 35 LBL_TREAT_MODELS_WITH_SUBPARTS_AS_PARTS */ {"treatmodelswithsubpartsasparts","1", QObject::tr("Treat Subparts As Parts"), QObject::tr("Treat subpart like a part by merging its constituent parts into one object")},
/* 36 LBL_TREAT_SHORTCUT_AS_MODEL */ {"treatshortcutasmodel", "0", QObject::tr("Treat Shortcuts As Models"),QObject::tr("Split shortcut parts into their constituent pieces as if they were models")},
/* 37 LBL_TRIANGULATE */ {"triangulate", "0", QObject::tr("Triangulate Faces"), QObject::tr("Triangulate all faces")},
/* 38 LBL_USE_ARCHIVE_LIBRARY_MM */ {"usearchivelibrary", "0", QObject::tr("Use Archive Libraries"), QObject::tr("Add any archive (zip) libraries in the LDraw file path to the library search list")},
/* 39 LBL_USE_FREESTYLE_EDGES */ {"usefreestyleedges", "0", QObject::tr("Use Freestyle Edges"), QObject::tr("Render LDraw edges using freestyle")},
/* 40 LBL_VERBOSE_MM */ {"verbose", "1", QObject::tr("Verbose output"), QObject::tr("Output all messages while working, else only show warnings and errors")},
/* 35 LBL_TREAT_SHORTCUT_AS_MODEL */ {"treatshortcutasmodel", "0", QObject::tr("Treat Shortcuts As Models"),QObject::tr("Split shortcut parts into their constituent pieces as if they were models")},
/* 36 LBL_TRIANGULATE */ {"triangulate", "0", QObject::tr("Triangulate Faces"), QObject::tr("Triangulate all faces")},
/* 37 LBL_USE_ARCHIVE_LIBRARY_MM */ {"usearchivelibrary", "0", QObject::tr("Use Archive Libraries"), QObject::tr("Add any archive (zip) libraries in the LDraw file path to the library search list")},
/* 38 LBL_USE_FREESTYLE_EDGES */ {"usefreestyleedges", "0", QObject::tr("Use Freestyle Edges"), QObject::tr("Render LDraw edges using freestyle")},
/* 39 LBL_VERBOSE_MM */ {"verbose", "1", QObject::tr("Verbose output"), QObject::tr("Output all messages while working, else only show warnings and errors")},
/* 41/00 LBL_BEVEL_SEGMENTS */ {"bevelsegments", "4", QObject::tr("Bevel Segments"), QObject::tr("Bevel segments")},
/* 42/01 LBL_BEVEL_WEIGHT */ {"bevelweight", "0.3", QObject::tr("Bevel Weight"), QObject::tr("Bevel weight")},
/* 43/02 LBL_BEVEL_WIDTH_MM */ {"bevelwidth", "0.3", QObject::tr("Bevel Width"), QObject::tr("Width of the bevelled edges")},
/* 44/03 LBL_CAMERA_BORDER_PERCENT_MM */ {"cameraborderpercent", "5", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border around the model in the render")},
/* 45/04 LBL_FRAMES_PER_STEP */ {"framesperstep", "3", QObject::tr("Frames Per Step"), QObject::tr("Frames per step")},
/* 46/05 LBL_GAP_SCALE */ {"gapscale", "0.997", QObject::tr("Gap Scale"), QObject::tr("Scale individual parts by this much to create the gap")},
/* 47/06 LBL_IMPORT_SCALE */ {"importscale", "0.02", QObject::tr("Import Scale"), QObject::tr("What scale to import at. Full scale is 1.0 and is so huge that it is unwieldy in the viewport")},
/* 48/07 LBL_MERGE_DISTANCE */ {"mergedistance", "0.05", QObject::tr("Merge Distance"), QObject::tr("Maximum distance between elements to merge")},
/* 49/08 LBL_RENDER_PERCENTAGE_MM */ {"renderpercentage", "100", QObject::tr("Render Percentage"), QObject::tr("Sets the rendered image percentage scale for its pixel resolution - updated from current step, label shows config setting.")},
/* 50/09 LBL_RESOLUTION_WIDTH */ {"resolutionwidth", "800", QObject::tr("Image Width"), QObject::tr("Sets the rendered image width in pixels - from current step image, label shows config setting.")},
/* 51/10 LBL_RESOLUTION_HEIGHT */ {"resolutionheight", "600", QObject::tr("Image Height"), QObject::tr("Sets the rendered image height in pixels - from current step image, label shows config setting.")},
/* 52/11 LBL_STARTING_STEP_FRAME */ {"startingstepframe", "1", QObject::tr("Starting Step Frame"), QObject::tr("Frame to add the first STEP meta command")},
/* 40/00 LBL_BEVEL_SEGMENTS */ {"bevelsegments", "4", QObject::tr("Bevel Segments"), QObject::tr("Bevel segments")},
/* 41/01 LBL_BEVEL_WEIGHT */ {"bevelweight", "0.3", QObject::tr("Bevel Weight"), QObject::tr("Bevel weight")},
/* 42/02 LBL_BEVEL_WIDTH_MM */ {"bevelwidth", "0.3", QObject::tr("Bevel Width"), QObject::tr("Width of the bevelled edges")},
/* 43/03 LBL_CAMERA_BORDER_PERCENT_MM */ {"cameraborderpercent", "5", QObject::tr("Camera Border Percent"), QObject::tr("When positioning the camera, include a (percentage) border around the model in the render")},
/* 44/04 LBL_FRAMES_PER_STEP */ {"framesperstep", "3", QObject::tr("Frames Per Step"), QObject::tr("Frames per step")},
/* 45/05 LBL_GAP_SCALE */ {"gapscale", "0.997", QObject::tr("Gap Scale"), QObject::tr("Scale individual parts by this much to create the gap")},
/* 46/06 LBL_IMPORT_SCALE */ {"importscale", "0.02", QObject::tr("Import Scale"), QObject::tr("What scale to import at. Full scale is 1.0 and is so huge that it is unwieldy in the viewport")},
/* 47/07 LBL_MERGE_DISTANCE */ {"mergedistance", "0.05", QObject::tr("Merge Distance"), QObject::tr("Maximum distance between elements to merge")},
/* 48/08 LBL_RENDER_PERCENTAGE_MM */ {"renderpercentage", "100", QObject::tr("Render Percentage"), QObject::tr("Sets the rendered image percentage scale for its pixel resolution - updated from current step, label shows config setting.")},
/* 49/09 LBL_RESOLUTION_WIDTH */ {"resolutionwidth", "800", QObject::tr("Image Width"), QObject::tr("Sets the rendered image width in pixels - from current step image, label shows config setting.")},
/* 50/10 LBL_RESOLUTION_HEIGHT */ {"resolutionheight", "600", QObject::tr("Image Height"), QObject::tr("Sets the rendered image height in pixels - from current step image, label shows config setting.")},
/* 51/11 LBL_STARTING_STEP_FRAME */ {"startingstepframe", "1", QObject::tr("Starting Step Frame"), QObject::tr("Frame to add the first STEP meta command")},
/* 53/00 LBL_CHOSEN_LOGO */ {"chosenlogo", "logo3", QObject::tr("Chosen Logo"), QObject::tr("Which logo to display. logo and logo2 aren't used and are only included for completeness")},
/* 54/01 LBL_COLOUR_SCHEME_MM */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")},
/* 55/02 LBL_GAP_SCALE_STRATEGY */ {"gapscalestrategy", "constraint", QObject::tr("Gap Strategy"), QObject::tr("Apply gap to object directly or scale and empty to adjust to gaps between parts")},
/* 56/03 LBL_GAP_TARGET */ {"gaptarget", "object", QObject::tr("Gap Target"), QObject::tr("Whether to scale the object data or mesh data")},
/* 57/04 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")},
/* 58/05 LBL_SMOOTH_TYPE */ {"smoothtype", "edge_split", QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")}
/* 52/00 LBL_CHOSEN_LOGO */ {"chosenlogo", "logo3", QObject::tr("Chosen Logo"), QObject::tr("Which logo to display. logo and logo2 aren't used and are only included for completeness")},
/* 53/01 LBL_COLOUR_SCHEME_MM */ {"usecolourscheme", "lgeo", QObject::tr("Colour Scheme"), QObject::tr("Colour scheme options - Realistic (lgeo), Original (LDConfig), Alternate (LDCfgalt), Custom (User Defined)")},
/* 54/02 LBL_COLOUR_STRATEGY */ {"colorstrategy", "material", QObject::tr("How To Color Parts"), QObject::tr("Colour strategy options - Material (Default - use if exporting), Vertex colors (slightly quicker to import)")},
/* 55/03 LBL_RESOLUTION_MM */ {"resolution", "Standard", QObject::tr("Resolution"), QObject::tr("Resolution of part primitives, ie. how much geometry they have")},
/* 56/04 LBL_SMOOTH_TYPE */ {"smoothtype", "edge_split", QObject::tr("Smooth Type"), QObject::tr("Use either autosmooth or an edge split modifier to smooth part faces")}
};
lcBlenderPreferences::ComboItems lcBlenderPreferences::mComboItemsMM [NUM_COMBO_ITEMS_MM] =
{
/* FIRST item set as default Data Item: */
/* 00 LBL_CHOSEN_LOGO */ {"logo|logo2|logo3", QObject::tr("Logo (Not Used)|Logo2 (Not Used)|Flattened(3)")},
/* 00 LBL_CHOSEN_LOGO */ {"logo3|logo4|logo5", QObject::tr("Raised flattened logo geometry(3)|Raised rounded logo geometry(4)|Subtle rounded logo geometry(5)")},
/* 01 LBL_COLOUR_SCHEME_MM */ {"lgeo|ldraw|alt|custom", QObject::tr("Realistic Colours|Original LDraw Colours|Alternate LDraw Colours|Custom Colours")},
/* 02 LBL_GAP_SCALE_STRATEGY */ {"object|constraint", QObject::tr("Gap applied directly to object|Gap scaled to adjust to gaps between parts")},
/* 03 LBL_GAP_TARGET */ {"object|mesh", QObject::tr("Scale object data|Scale mesh data")},
/* 04 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")},
/* 05 LBL_SMOOTH_TYPE */ {"edge_split|auto_smooth|bmesh_split", QObject::tr("Smooth part faces with edge split modifier|Auto-smooth part faces|Split during initial mesh processing")}
/* 02 LBL_COLOUR_STRATEGY */ {"material|vertex_colors", QObject::tr("Material|Vertex Colors")},
/* 03 LBL_RESOLUTION_MM */ {"Low|Standard|High", QObject::tr("Low Resolution Primitives|Standard Primitives|High Resolution Primitives")},
/* 04 LBL_SMOOTH_TYPE */ {"edge_split|auto_smooth|bmesh_split", QObject::tr("Smooth part faces with edge split modifier|Auto-smooth part faces|Split during initial mesh processing")}
};
lcBlenderPreferences* gAddonPreferences;
@ -441,31 +442,40 @@ lcBlenderPreferences::lcBlenderPreferences(int Width, int Height, double Scale,
mAddonGridLayout = new QGridLayout(BlenderAddonVersionBox);
BlenderAddonVersionBox->setLayout(mAddonGridLayout);
QCheckBox* AddonVersionCheck = new QCheckBox(tr("Prompt to download new addon version when available"), BlenderAddonVersionBox);
AddonVersionCheck->setChecked(lcGetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK));
QObject::connect(AddonVersionCheck, &QCheckBox::stateChanged, [](int State)
{
const bool VersionCheck = static_cast<Qt::CheckState>(State) == Qt::CheckState::Checked;
lcSetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK, (int)VersionCheck);
});
mAddonGridLayout->addWidget(AddonVersionCheck,0,0,1,4);
mAddonVersionLabel = new QLabel(BlenderAddonVersionBox);
mAddonGridLayout->addWidget(mAddonVersionLabel,0,0);
mAddonGridLayout->addWidget(mAddonVersionLabel,1,0);
mAddonVersionEdit = new QLineEdit(BlenderAddonVersionBox);
mAddonVersionEdit->setToolTip(tr("%1 Blender LDraw import and image renderer addon").arg(LC_PRODUCTNAME_STR));
mAddonVersionEdit->setPalette(ReadOnlyPalette);
mAddonVersionEdit->setReadOnly(true);
mAddonGridLayout->addWidget(mAddonVersionEdit,0,1);
mAddonGridLayout->addWidget(mAddonVersionEdit,1,1);
mAddonGridLayout->setColumnStretch(1,1/*1 is greater than 0 (default)*/);
mAddonUpdateButton = new QPushButton(tr("Update"), BlenderAddonVersionBox);
mAddonUpdateButton->setToolTip(tr("Update %1 Blender LDraw addon").arg(LC_PRODUCTNAME_STR));
mAddonGridLayout->addWidget(mAddonUpdateButton,0,2);
mAddonGridLayout->addWidget(mAddonUpdateButton,1,2);
connect(mAddonUpdateButton, SIGNAL(clicked(bool)), this, SLOT(UpdateBlenderAddon()));
mAddonStdOutButton = new QPushButton(tr("Output..."), BlenderAddonVersionBox);
mAddonStdOutButton->setToolTip(tr("Open the standrd output log"));
mAddonStdOutButton->setEnabled(false);
mAddonGridLayout->addWidget(mAddonStdOutButton,0,3);
mAddonGridLayout->addWidget(mAddonStdOutButton,1,3);
connect(mAddonStdOutButton, SIGNAL(clicked(bool)), this, SLOT(GetStandardOutput()));
mModulesBox = new QGroupBox(tr("Enabled Addon Modules"),mContent);
QHBoxLayout* ModulesLayout = new QHBoxLayout(mModulesBox);
mModulesBox->setLayout(ModulesLayout);
mAddonGridLayout->addWidget(mModulesBox,1,0,1,4);
mAddonGridLayout->addWidget(mModulesBox,2,0,1,4);
mImportActBox = new QCheckBox(tr("LDraw Import TN"),mModulesBox);
mImportActBox->setToolTip(tr("Enable addon import module (adapted from LDraw Import by Toby Nelson) in Blender"));
@ -1440,18 +1450,25 @@ bool lcBlenderPreferences::GetBlenderAddon(const QString& BlenderDir)
}
else if (gMainWindow)
{
if (LocalVersion.isEmpty())
LocalVersion = gAddonPreferences->mAddonVersion;
const QString& Title = tr ("%1 Blender LDraw Addon").arg(LC_PRODUCTNAME_STR);
const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR).arg(LocalVersion).arg(OnlineVersion);
const QString& Body = tr ("Do you want to download version %1 ?").arg(OnlineVersion);
int Exec = ShowMessage(Header, Title, Body, QString(), MBB_YES, QMessageBox::NoIcon);
if (Exec == QMessageBox::Cancel)
if (lcGetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK))
{
AddonStatus = tr("Blender addon setup cancelled");
AddonAction = ADDON_CANCEL;
if (LocalVersion.isEmpty())
LocalVersion = gAddonPreferences->mAddonVersion;
const QString& Title = tr ("%1 Blender LDraw Addon").arg(LC_PRODUCTNAME_STR);
const QString& Header = tr ("Detected %1 Blender LDraw addon %2. A newer version %3 exists.").arg(LC_PRODUCTNAME_STR).arg(LocalVersion).arg(OnlineVersion);
const QString& Body = tr ("Do you want to download version %1 ?").arg(OnlineVersion);
int Exec = ShowMessage(Header, Title, Body, QString(), MBB_YES, QMessageBox::NoIcon);
if (Exec == QMessageBox::Cancel)
{
AddonStatus = tr("Blender addon setup cancelled");
AddonAction = ADDON_CANCEL;
}
else if (Exec == QMessageBox::No)
{
AddonAction = ADDON_RELOAD;
}
}
else if (Exec == QMessageBox::No)
else
{
AddonAction = ADDON_RELOAD;
}
@ -2586,7 +2603,9 @@ void lcBlenderPreferences::SaveSettings()
continue;
Key = mBlenderPaths[LblIdx].key;
Value = QDir::toNativeSeparators(mBlenderPaths[LblIdx].value);
Settings.setValue(Key, QVariant(Value));
if (Settings.contains(Key))
Settings.setValue(Key, QVariant(Value));
}
for (int LblIdx = 0; LblIdx < NumSettings(); LblIdx++)
@ -2608,7 +2627,9 @@ void lcBlenderPreferences::SaveSettings()
}
Key = mBlenderSettings[LblIdx].key;
Settings.setValue(Key, QVariant(Value));
if (Settings.contains(Key))
Settings.setValue(Key, QVariant(Value));
}
Settings.setValue(parameterFileKey, QVariant(QDir::toNativeSeparators(ParameterFile)));
@ -2625,7 +2646,9 @@ void lcBlenderPreferences::SaveSettings()
continue;
Key = mBlenderPaths[LblIdx].key_mm;
Value = QDir::toNativeSeparators(mBlenderPaths[LblIdx].value);
Settings.setValue(Key, QVariant(Value));
if (Settings.contains(Key))
Settings.setValue(Key, QVariant(Value));
}
for (int LblIdx = 0; LblIdx < NumSettingsMM(); LblIdx++)
@ -2644,7 +2667,9 @@ void lcBlenderPreferences::SaveSettings()
}
Key = mBlenderSettingsMM[LblIdx].key;
Settings.setValue(Key, QVariant(Value));
if (Settings.contains(Key))
Settings.setValue(Key, QVariant(Value));
}
searchDirectoriesKey = QLatin1String("additionalSearchPaths");
@ -3462,6 +3487,20 @@ int lcBlenderPreferences::ShowMessage(const QString& Header, const QString& Tit
}
}
const bool DownloadRequest = Body.startsWith(tr("Do you want to download version "));
if (DownloadRequest){
QCheckBox* AddonVersionCheck = new QCheckBox(tr("Do not show download new addon version message again."));
Box.setCheckBox(AddonVersionCheck);
QObject::connect(AddonVersionCheck, &QCheckBox::stateChanged, [](int State)
{
bool VersionCheck = true;
if (static_cast<Qt::CheckState>(State) == Qt::CheckState::Checked)
VersionCheck = false;
lcSetProfileInt(LC_PROFILE_BLENDER_ADDON_VERSION_CHECK, (int)VersionCheck);
});
}
return Box.exec();
}

View file

@ -237,30 +237,30 @@ private:
LBL_ADD_ENVIRONMENT_MM, // 0 QCheckBox
LBL_BEVEL_EDGES_MM, // 1 QCheckBox
LBL_BLEND_FILE_TRUSTED_MM, // 2 QCheckBox
LBL_CROP_IMAGE_MM, // 3 QCheckBox
LBL_DISPLAY_LOGO, // 4 QCheckBox
LBL_IMPORT_CAMERAS_MM, // 5 QCheckBox
LBL_IMPORT_EDGES, // 6 QCheckBox
LBL_CASE_SENSITIVE_FILESYSTEM, // 3 QCheckBox
LBL_CROP_IMAGE_MM, // 4 QCheckBox
LBL_DISPLAY_LOGO, // 5 QCheckBox
LBL_IMPORT_CAMERAS_MM, // 6 QCheckBox
NUM_COMBO_ITEMS_MM, // 7
LBL_IMPORT_LIGHTS_MM = NUM_COMBO_ITEMS_MM, // 7 QCheckBox
LBL_KEEP_ASPECT_RATIO_MM, // 8 QCheckBox
LBL_MAKE_GAPS, // 9 QCheckBox
LBL_META_BFC, // 10 QCheckBox
LBL_META_CLEAR, // 11 QCheckBox
LBL_META_GROUP, // 12 QCheckBox
LBL_META_PAUSE, // 13 QCheckBox
LBL_META_PRINT_WRITE, // 14 QCheckBox
LBL_META_SAVE, // 15 QCheckBox
LBL_META_STEP, // 16 QCheckBox
LBL_META_STEP_GROUPS, // 17 QCheckBox
LBL_META_TEXMAP, // 18 QCheckBox
LBL_NO_STUDS, // 19 QCheckBox
LBL_OVERWRITE_IMAGE_MM, // 20 QCheckBox
LBL_POSITION_CAMERA_MM, // 21 QCheckBox
LBL_PARENT_TO_EMPTY, // 22 QCheckBox
LBL_PREFER_STUDIO, // 23 QCheckBox
LBL_PREFER_UNOFFICIAL, // 24 QCheckBox
LBL_PRESERVE_HIERARCHY, // 25 QCheckBox
LBL_IMPORT_EDGES = NUM_COMBO_ITEMS_MM, // 7 QCheckBox
LBL_IMPORT_LIGHTS_MM, // 8 QCheckBox
LBL_KEEP_ASPECT_RATIO_MM, // 9 QCheckBox
LBL_MAKE_GAPS, // 10 QCheckBox
LBL_META_BFC, // 11 QCheckBox
LBL_META_CLEAR, // 12 QCheckBox
LBL_META_GROUP, // 13 QCheckBox
LBL_META_PAUSE, // 14 QCheckBox
LBL_META_PRINT_WRITE, // 15 QCheckBox
LBL_META_SAVE, // 16 QCheckBox
LBL_META_STEP, // 17 QCheckBox
LBL_META_STEP_GROUPS, // 18 QCheckBox
LBL_META_TEXMAP, // 19 QCheckBox
LBL_NO_STUDS, // 20 QCheckBox
LBL_OVERWRITE_IMAGE_MM, // 21 QCheckBox
LBL_POSITION_CAMERA_MM, // 22 QCheckBox
LBL_PARENT_TO_EMPTY, // 23 QCheckBox
LBL_PREFER_STUDIO, // 24 QCheckBox
LBL_PREFER_UNOFFICIAL, // 25 QCheckBox
LBL_PROFILE, // 26 QCheckBox
LBL_RECALCULATE_NORMALS, // 27 QCheckBox
LBL_REMOVE_DOUBLES_MM, // 28 QCheckBox
@ -270,32 +270,30 @@ private:
LBL_SET_TIMELINE_MARKERS, // 32 QCheckBox
LBL_SHADE_SMOOTH, // 33 QCheckBox
LBL_TRANSPARENT_BACKGROUND_MM, // 34 QCheckBox
LBL_TREAT_MODELS_WITH_SUBPARTS_AS_PARTS, // 35 QCheckBox
LBL_TREAT_SHORTCUT_AS_MODEL, // 36 QCheckBox
LBL_TRIANGULATE, // 37 QCheckBox
LBL_USE_ARCHIVE_LIBRARY_MM, // 38 QCheckBox
LBL_USE_FREESTYLE_EDGES, // 39 QCheckBox
LBL_VERBOSE_MM, // 40 QCheckBox
LBL_TREAT_SHORTCUT_AS_MODEL, // 35 QCheckBox
LBL_TRIANGULATE, // 36 QCheckBox
LBL_USE_ARCHIVE_LIBRARY_MM, // 37 QCheckBox
LBL_USE_FREESTYLE_EDGES, // 38 QCheckBox
LBL_VERBOSE_MM, // 39 QCheckBox
LBL_BEVEL_SEGMENTS, // 41/ 0 QLineEdit
LBL_BEVEL_WEIGHT, // 42/ 1 QLineEdit
LBL_BEVEL_WIDTH_MM, // 43/ 2 QLineEdit
LBL_CAMERA_BORDER_PERCENT_MM, // 44/ 3 QLineEdit
LBL_FRAMES_PER_STEP, // 45/ 4 QLineEdit
LBL_GAP_SCALE, // 46/ 5 QLineEdit
LBL_IMPORT_SCALE, // 47/ 6 QLineEdit
LBL_MERGE_DISTANCE, // 48/ 7 QLineEdit
LBL_RENDER_PERCENTAGE_MM, // 49/ 8 QLineEdit
LBL_RESOLUTION_WIDTH, // 50/ 9 QLineEdit
LBL_RESOLUTION_HEIGHT, // 51/10 QLineEdit
LBL_STARTING_STEP_FRAME, // 52/11 QLineEdit
LBL_BEVEL_SEGMENTS, // 40/ 0 QLineEdit
LBL_BEVEL_WEIGHT, // 41/ 1 QLineEdit
LBL_BEVEL_WIDTH_MM, // 42/ 2 QLineEdit
LBL_CAMERA_BORDER_PERCENT_MM, // 43/ 3 QLineEdit
LBL_FRAMES_PER_STEP, // 44/ 4 QLineEdit
LBL_GAP_SCALE, // 45/ 5 QLineEdit
LBL_IMPORT_SCALE, // 46/ 6 QLineEdit
LBL_MERGE_DISTANCE, // 47/ 7 QLineEdit
LBL_RENDER_PERCENTAGE_MM, // 48/ 8 QLineEdit
LBL_RESOLUTION_WIDTH, // 49/ 9 QLineEdit
LBL_RESOLUTION_HEIGHT, // 50/10 QLineEdit
LBL_STARTING_STEP_FRAME, // 51/11 QLineEdit
LBL_CHOSEN_LOGO, // 53/ 0 QComboBox
LBL_COLOUR_SCHEME_MM, // 54/ 1 QComboBox
LBL_GAP_SCALE_STRATEGY, // 55/ 2 QComboBox
LBL_GAP_TARGET, // 56/ 3 QComboBox
LBL_RESOLUTION_MM, // 57/ 4 QComboBox
LBL_SMOOTH_TYPE, // 58/ 5 QComboBox
LBL_CHOSEN_LOGO, // 52/ 0 QComboBox
LBL_COLOUR_SCHEME_MM, // 53/ 1 QComboBox
LBL_COLOUR_STRATEGY, // 54/ 2 QComboBox
LBL_RESOLUTION_MM, // 55/ 3 QComboBox
LBL_SMOOTH_TYPE, // 56/ 4 QComboBox
NUM_SETTINGS_MM
};
@ -311,42 +309,41 @@ private:
CTL_COLOUR_SCHEME_COMBO_MM = CTL_BEVEL_EDGES_BOX_MM, // 1
CTL_BLEND_FILE_TRUSTED_BOX_MM, // 2
CTL_BEVEL_WIDTH_EDIT_MM = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2
CTL_GAP_SCALE_STRATEGY_COMBO = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2
CTL_CROP_IMAGE_BOX_MM, // 3
CTL_CAMERA_BORDER_PERCENT_EDIT_MM = CTL_CROP_IMAGE_BOX_MM, // 3
CTL_GAP_TARGET_COMBO = CTL_CROP_IMAGE_BOX_MM, // 3
CTL_DISPLAY_LOGO_BOX, // 4
CTL_FRAMES_PER_STEP_EDIT = CTL_DISPLAY_LOGO_BOX, // 4
CTL_RESOLUTION_COMBO_MM = CTL_DISPLAY_LOGO_BOX, // 4
CTL_IMPORT_CAMERAS_BOX_MM, // 5
CTL_GAP_SCALE_EDIT = CTL_IMPORT_CAMERAS_BOX_MM, // 5
CTL_SMOOTH_TYPE_COMBO = CTL_IMPORT_CAMERAS_BOX_MM, // 5
CTL_IMPORT_EDGES_BOX, // 6
CTL_IMPORT_SCALE_EDIT = CTL_IMPORT_EDGES_BOX, // 6
CTL_IMPORT_LIGHTS_BOX_MM, // 7
CTL_MERGE_DISTANCE_EDIT = CTL_IMPORT_LIGHTS_BOX_MM, // 7
CTL_KEEP_ASPECT_RATIO_BOX_MM, // 8
CTL_RENDER_PERCENTAGE_EDIT_MM = CTL_KEEP_ASPECT_RATIO_BOX_MM, // 8
CTL_MAKE_GAPS_BOX, // 9
CTL_RESOLUTION_WIDTH_EDIT = CTL_MAKE_GAPS_BOX, // 9
CTL_META_BFC_BOX, // 10
CTL_RESOLUTION_HEIGHT_EDIT = CTL_META_BFC_BOX, // 10
CTL_META_CLEAR_BOX, // 11
CTL_STARTING_STEP_FRAME_EDIT = CTL_META_CLEAR_BOX, // 11
CTL_META_GROUP_BOX, // 12
CTL_META_PAUSE_BOX, // 13
CTL_META_PRINT_WRITE_BOX, // 14
CTL_META_SAVE_BOX, // 15
CTL_META_STEP_BOX, // 16
CTL_META_STEP_GROUPS_BOX, // 17
CTL_META_TEXMAP_BOX, // 18
CTL_NO_STUDS_BOX, // 19
CTL_POSITION_CAMERA_BOX_MM, // 10
CTL_OVERWRITE_IMAGE_BOX_MM, // 21
CTL_PARENT_TO_EMPTY_BOX, // 22
CTL_PREFER_STUDIO_BOX, // 23
CTL_PREFER_UNOFFICIAL_BOX, // 24
CTL_PRESERVE_HIERARCHY_BOX, // 25
CTL_COLOUR_STRATEGY_COMBO = CTL_BLEND_FILE_TRUSTED_BOX_MM,// 2
CTL_CASE_SENSITIVE_FILESYSTEM_BOX, // 3
CTL_CAMERA_BORDER_PERCENT_EDIT_MM = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3
CTL_RESOLUTION_COMBO_MM = CTL_CASE_SENSITIVE_FILESYSTEM_BOX,// 3
CTL_CROP_IMAGE_BOX_MM, // 4
CTL_FRAMES_PER_STEP_EDIT = CTL_CROP_IMAGE_BOX_MM, // 4
CTL_SMOOTH_TYPE_COMBO = CTL_CROP_IMAGE_BOX_MM, // 4
CTL_DISPLAY_LOGO_BOX, // 5
CTL_GAP_SCALE_EDIT = CTL_DISPLAY_LOGO_BOX, // 5
CTL_IMPORT_CAMERAS_BOX_MM, // 6
CTL_IMPORT_SCALE_EDIT = CTL_IMPORT_CAMERAS_BOX_MM, // 6
CTL_IMPORT_EDGES_BOX, // 7
CTL_MERGE_DISTANCE_EDIT = CTL_IMPORT_EDGES_BOX, // 7
CTL_IMPORT_LIGHTS_BOX_MM, // 8
CTL_RENDER_PERCENTAGE_EDIT_MM = CTL_IMPORT_LIGHTS_BOX_MM, // 8
CTL_KEEP_ASPECT_RATIO_BOX_MM, // 9
CTL_RESOLUTION_WIDTH_EDIT = CTL_KEEP_ASPECT_RATIO_BOX_MM, // 9
CTL_MAKE_GAPS_BOX, // 10
CTL_RESOLUTION_HEIGHT_EDIT = CTL_MAKE_GAPS_BOX, // 10
CTL_META_BFC_BOX, // 11
CTL_STARTING_STEP_FRAME_EDIT = CTL_META_BFC_BOX, // 11
CTL_META_CLEAR_BOX, // 12
CTL_META_GROUP_BOX, // 13
CTL_META_PAUSE_BOX, // 14
CTL_META_PRINT_WRITE_BOX, // 15
CTL_META_SAVE_BOX, // 16
CTL_META_STEP_BOX, // 17
CTL_META_STEP_GROUPS_BOX, // 18
CTL_META_TEXMAP_BOX, // 19
CTL_NO_STUDS_BOX, // 20
CTL_POSITION_CAMERA_BOX_MM, // 21
CTL_OVERWRITE_IMAGE_BOX_MM, // 22
CTL_PARENT_TO_EMPTY_BOX, // 23
CTL_PREFER_STUDIO_BOX, // 24
CTL_PREFER_UNOFFICIAL_BOX, // 25
CTL_PROFILE_BOX, // 26
CTL_RECALCULATE_NORMALS_BOX, // 27
CTL_REMOVE_DOUBLES_BOX_MM, // 28
@ -356,12 +353,11 @@ private:
CTL_SET_TIMELINE_MARKERS_BOX, // 32
CTL_SHADE_SMOOTH_BOX, // 33
CTL_TRANSPARENT_BACKGROUND_BOX_MM, // 34
CTL_TREAT_MODELS_WITH_SUBPARTS_AS_PARTS_BOX, // 35
CTL_TREAT_SHORTCUT_AS_MODEL_BOX, // 36
CTL_TRIANGULATE_BOX, // 37
CTL_USE_ARCHIVE_LIBRARY_BOX_MM, // 38
CTL_USE_FREESTYLE_EDGES_BOX, // 39
CTL_VERBOSE_BOX_MM // 40
CTL_TREAT_SHORTCUT_AS_MODEL_BOX, // 35
CTL_TRIANGULATE_BOX, // 36
CTL_USE_ARCHIVE_LIBRARY_BOX_MM, // 37
CTL_USE_FREESTYLE_EDGES_BOX, // 38
CTL_VERBOSE_BOX_MM // 39
};
enum BlenderBrickType

View file

@ -85,6 +85,8 @@ static std::vector<lcColor> lcParseColorFile(lcFile& File)
Color.Code = ~0U;
Color.Translucent = false;
Color.Chrome = false;
Color.Rubber = false;
Color.Group = LC_COLORGROUP_SOLID;
Color.Value[0] = FLT_MAX;
Color.Value[1] = FLT_MAX;
@ -157,8 +159,17 @@ static std::vector<lcColor> lcParseColorFile(lcFile& File)
else if (Value != 0)
Color.Group = LC_COLORGROUP_SPECIAL;
}
else if (!strcmp(Token, "CHROME") || !strcmp(Token, "PEARLESCENT") || !strcmp(Token, "RUBBER") ||
!strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE"))
else if (!strcmp(Token, "CHROME"))
{
Color.Chrome = true;
Color.Group = LC_COLORGROUP_SPECIAL;
}
else if (!strcmp(Token, "RUBBER"))
{
Color.Rubber = true;
Color.Group = LC_COLORGROUP_SPECIAL;
}
else if (!strcmp(Token, "PEARLESCENT") || !strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE"))
{
Color.Group = LC_COLORGROUP_SPECIAL;
}
@ -236,6 +247,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
MainColor.Code = 16;
MainColor.Translucent = false;
MainColor.Chrome = false;
MainColor.Rubber = false;
MainColor.Group = LC_COLORGROUP_SOLID;
MainColor.Value[0] = 1.0f;
MainColor.Value[1] = 1.0f;
@ -257,6 +270,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
EdgeColor.Code = 24;
EdgeColor.Translucent = false;
EdgeColor.Chrome = false;
EdgeColor.Rubber = false;
EdgeColor.Group = LC_NUM_COLORGROUPS;
EdgeColor.Value[0] = 0.5f;
EdgeColor.Value[1] = 0.5f;
@ -279,6 +294,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
StudCylinderColor.Code = LC_STUD_CYLINDER_COLOR_CODE;
StudCylinderColor.Translucent = false;
StudCylinderColor.Chrome = false;
StudCylinderColor.Rubber = false;
StudCylinderColor.Group = LC_NUM_COLORGROUPS;
StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor);
StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor);
@ -294,6 +311,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
NoColor.Code = LC_COLOR_NOCOLOR;
NoColor.Translucent = false;
NoColor.Chrome = false;
NoColor.Rubber = false;
NoColor.Group = LC_NUM_COLORGROUPS;
NoColor.Value[0] = 0.5f;
NoColor.Value[1] = 0.5f;
@ -362,6 +381,8 @@ int lcGetColorIndex(quint32 ColorCode)
Color.Code = ColorCode;
Color.Translucent = false;
Color.Chrome = false;
Color.Rubber = false;
Color.Edge[0] = 0.2f;
Color.Edge[1] = 0.2f;
Color.Edge[2] = 0.2f;

View file

@ -13,6 +13,8 @@ struct lcColor
quint32 Code;
int Group;
bool Translucent = false;
bool Chrome = false;
bool Rubber = false;
bool Adjusted = false;
lcVector4 Value;
lcVector4 Edge;
@ -64,3 +66,13 @@ inline bool lcIsColorTranslucent(size_t ColorIndex)
{
return gColorList[ColorIndex].Translucent;
}
inline bool lcIsColorChrome(size_t ColorIndex)
{
return gColorList[ColorIndex].Chrome;
}
inline bool lcIsColorRubber(size_t ColorIndex)
{
return gColorList[ColorIndex].Rubber;
}

View file

@ -333,46 +333,46 @@ const lcCommand gCommands[] =
QT_TRANSLATE_NOOP("Status", "Select all pieces of the same type and color"),
""
},
// LC_EDIT_TRANSFORM_RELATIVE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformRelative"),
QT_TRANSLATE_NOOP("Menu", "Relative Transforms"),
QT_TRANSLATE_NOOP("Status", "Move and rotate objects relative to the one that has focus"),
""
},
// LC_EDIT_TRANSFORM_ABSOLUTE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformAbsolute"),
QT_TRANSLATE_NOOP("Menu", "Absolute Transforms"),
QT_TRANSLATE_NOOP("Status", "Move and rotate objects in absolute coordinates"),
""
},
// LC_EDIT_TRANSFORM_TOGGLE_RELATIVE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleRelative"),
QT_TRANSLATE_NOOP("Menu", "Toggle Relative Transforms"),
QT_TRANSLATE_NOOP("Status", "Toggle moving and rotating objects relative to the one that has focus"),
// LC_EDIT_TRANSFORM_RELATIVE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformRelative"),
QT_TRANSLATE_NOOP("Menu", "Relative Transforms"),
QT_TRANSLATE_NOOP("Status", "Move and rotate objects relative to the one that has focus"),
""
},
// LC_EDIT_TRANSFORM_SEPARATELY
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformSeparately"),
QT_TRANSLATE_NOOP("Menu", "Rotate Separately"),
QT_TRANSLATE_NOOP("Status", "Rotate selected pieces separately"),
""
},
// LC_EDIT_TRANSFORM_TOGETHER
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformTogether"),
QT_TRANSLATE_NOOP("Menu", "Rotate Together"),
QT_TRANSLATE_NOOP("Status", "Rotate selected pieces together"),
""
},
// LC_EDIT_TRANSFORM_TOGGLE_SEPARATE
// LC_EDIT_TRANSFORM_ABSOLUTE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleSeparate"),
QT_TRANSLATE_NOOP("Menu", "Toggle Separate Transforms"),
QT_TRANSLATE_NOOP("Status", "Toggle rotating selected pieces separately"),
QT_TRANSLATE_NOOP("Action", "Edit.TransformAbsolute"),
QT_TRANSLATE_NOOP("Menu", "Absolute Transforms"),
QT_TRANSLATE_NOOP("Status", "Move and rotate objects in absolute coordinates"),
""
},
// LC_EDIT_TRANSFORM_TOGGLE_RELATIVE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleRelative"),
QT_TRANSLATE_NOOP("Menu", "Toggle Relative Transforms"),
QT_TRANSLATE_NOOP("Status", "Toggle moving and rotating objects relative to the one that has focus"),
""
},
// LC_EDIT_TRANSFORM_SEPARATELY
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformSeparately"),
QT_TRANSLATE_NOOP("Menu", "Rotate Separately"),
QT_TRANSLATE_NOOP("Status", "Rotate selected pieces separately"),
""
},
// LC_EDIT_TRANSFORM_TOGETHER
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformTogether"),
QT_TRANSLATE_NOOP("Menu", "Rotate Together"),
QT_TRANSLATE_NOOP("Status", "Rotate selected pieces together"),
""
},
// LC_EDIT_TRANSFORM_TOGGLE_SEPARATE
{
QT_TRANSLATE_NOOP("Action", "Edit.TransformToggleSeparate"),
QT_TRANSLATE_NOOP("Menu", "Toggle Separate Transforms"),
QT_TRANSLATE_NOOP("Status", "Toggle rotating selected pieces separately"),
""
},
// LC_EDIT_SNAP_MOVE_TOGGLE
@ -641,18 +641,32 @@ const lcCommand gCommands[] =
QT_TRANSLATE_NOOP("Status", "Add new pieces to the model"),
""
},
// LC_EDIT_ACTION_LIGHT
// LC_EDIT_ACTION_POINT_LIGHT
{
QT_TRANSLATE_NOOP("Action", "Edit.Tool.Light"),
QT_TRANSLATE_NOOP("Menu", "Light"),
QT_TRANSLATE_NOOP("Status", "Add new omni light sources to the model"),
QT_TRANSLATE_NOOP("Action", "Edit.Tool.PointLight"),
QT_TRANSLATE_NOOP("Menu", "Point Light"),
QT_TRANSLATE_NOOP("Status", "Add new point light sources to the model"),
""
},
// LC_EDIT_ACTION_SPOTLIGHT
{
QT_TRANSLATE_NOOP("Action", "Edit.Tool.Spotlight"),
QT_TRANSLATE_NOOP("Menu", "Spotlight"),
QT_TRANSLATE_NOOP("Status", "Add new spotlights to the model"),
QT_TRANSLATE_NOOP("Action", "Edit.Tool.SpotLight"),
QT_TRANSLATE_NOOP("Menu", "Spot Light"),
QT_TRANSLATE_NOOP("Status", "Add new spot lights to the model"),
""
},
// LC_EDIT_ACTION_DIRECTIONAL_LIGHT
{
QT_TRANSLATE_NOOP("Action", "Edit.Tool.DirectionalLight"),
QT_TRANSLATE_NOOP("Menu", "Directional Light"),
QT_TRANSLATE_NOOP("Status", "Add new omnidirectional light sources to the model"),
""
},
// LC_EDIT_ACTION_AREA_LIGHT
{
QT_TRANSLATE_NOOP("Action", "Edit.Tool.AreaLight"),
QT_TRANSLATE_NOOP("Menu", "Area Light"),
QT_TRANSLATE_NOOP("Status", "Add new area light sources to the model"),
""
},
// LC_EDIT_ACTION_CAMERA
@ -1362,7 +1376,7 @@ const lcCommand gCommands[] =
QT_TRANSLATE_NOOP("Status", "Make copies of the selected pieces"),
""
},
// LC_PIECE_VIEW_SELECTED_MODEL
// LC_PIECE_VIEW_SELECTED_MODEL
{
QT_TRANSLATE_NOOP("Action", "Piece.ViewSelectedModel"),
QT_TRANSLATE_NOOP("Menu", "Open Selected Model"),
@ -1858,21 +1872,23 @@ LC_ARRAY_SIZE_CHECK(gCommands, LC_NUM_COMMANDS);
const char* gToolNames[] =
{
QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert
QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::Light
QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight
QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera
QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select
QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move
QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate
QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser
QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint
QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker
QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom
QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan
QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView
QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll
QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion
QT_TRANSLATE_NOOP("Mouse", "NewPiece"), // lcTool::Insert
QT_TRANSLATE_NOOP("Mouse", "NewPointLight"), // lcTool::PointLight
QT_TRANSLATE_NOOP("Mouse", "NewSpotLight"), // lcTool::SpotLight
QT_TRANSLATE_NOOP("Mouse", "NewDirectionalLight"), // lcTool::DirectionalLight
QT_TRANSLATE_NOOP("Mouse", "NewAreaLight"), // lcTool::AreaLight
QT_TRANSLATE_NOOP("Mouse", "NewCamera"), // lcTool::Camera
QT_TRANSLATE_NOOP("Mouse", "Select"), // lcTool::Select
QT_TRANSLATE_NOOP("Mouse", "Move"), // lcTool::Move
QT_TRANSLATE_NOOP("Mouse", "Rotate"), // lcTool::Rotate
QT_TRANSLATE_NOOP("Mouse", "Delete"), // lcTool::Eraser
QT_TRANSLATE_NOOP("Mouse", "Paint"), // lcTool::Paint
QT_TRANSLATE_NOOP("Mouse", "ColorPicker"), // lcTool::ColorPicker
QT_TRANSLATE_NOOP("Mouse", "Zoom"), // lcTool::Zoom
QT_TRANSLATE_NOOP("Mouse", "Pan"), // lcTool::Pan
QT_TRANSLATE_NOOP("Mouse", "Orbit"), // lcTool::RotateView
QT_TRANSLATE_NOOP("Mouse", "Roll"), // lcTool::Roll
QT_TRANSLATE_NOOP("Mouse", "ZoomRegion") // lcTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(gToolNames, lcTool::Count);

View file

@ -98,8 +98,10 @@ enum lcCommandId
LC_EDIT_TRANSFORM_RELATIVE_ROTATION,
LC_EDIT_ACTION_FIRST,
LC_EDIT_ACTION_INSERT = LC_EDIT_ACTION_FIRST,
LC_EDIT_ACTION_LIGHT,
LC_EDIT_ACTION_POINT_LIGHT,
LC_EDIT_ACTION_SPOTLIGHT,
LC_EDIT_ACTION_DIRECTIONAL_LIGHT,
LC_EDIT_ACTION_AREA_LIGHT,
LC_EDIT_ACTION_CAMERA,
LC_EDIT_ACTION_SELECT,
LC_EDIT_ACTION_MOVE,
@ -298,8 +300,10 @@ extern const lcCommand gCommands[];
enum class lcTool
{
Insert,
Light,
PointLight,
SpotLight,
DirectionalLight,
AreaLight,
Camera,
Select,
Move,

View file

@ -75,6 +75,8 @@ class lcObject;
class lcPiece;
class lcCamera;
class lcLight;
enum class lcLightType;
enum class lcLightAreaShape;
class lcGroup;
class PieceInfo;
typedef std::map<const PieceInfo*, std::map<int, int>> lcPartsList;

View file

@ -204,13 +204,23 @@ void lcMainWindow::CreateActions()
QIcon EditActionLightIcon;
EditActionLightIcon.addFile(":/resources/action_light.png");
EditActionLightIcon.addFile(":/resources/action_light_16.png");
mActions[LC_EDIT_ACTION_LIGHT]->setIcon(EditActionLightIcon);
mActions[LC_EDIT_ACTION_POINT_LIGHT]->setIcon(EditActionLightIcon);
QIcon EditActionSpotLightIcon;
EditActionSpotLightIcon.addFile(":/resources/action_spotlight.png");
EditActionSpotLightIcon.addFile(":/resources/action_spotlight_16.png");
mActions[LC_EDIT_ACTION_SPOTLIGHT]->setIcon(EditActionSpotLightIcon);
QIcon EditActionSunlightIcon;
EditActionSunlightIcon.addFile(":/resources/action_sunlight.png");
EditActionSunlightIcon.addFile(":/resources/action_sunlight_16.png");
mActions[LC_EDIT_ACTION_DIRECTIONAL_LIGHT]->setIcon(EditActionSunlightIcon);
QIcon EditActionArealightIcon;
EditActionArealightIcon.addFile(":/resources/action_arealight.png");
EditActionArealightIcon.addFile(":/resources/action_arealight_16.png");
mActions[LC_EDIT_ACTION_AREA_LIGHT]->setIcon(EditActionArealightIcon);
QIcon EditActionSelectIcon;
EditActionSelectIcon.addFile(":/resources/action_select.png");
EditActionSelectIcon.addFile(":/resources/action_select_16.png");
@ -421,8 +431,10 @@ void lcMainWindow::CreateMenus()
mToolsMenu = new QMenu(tr("Tools"), this);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_INSERT]);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_LIGHT]);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_POINT_LIGHT]);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SPOTLIGHT]);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_DIRECTIONAL_LIGHT]);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_AREA_LIGHT]);
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_CAMERA]);
mToolsMenu->addSeparator();
mToolsMenu->addAction(mActions[LC_EDIT_ACTION_SELECT]);
@ -664,8 +676,10 @@ void lcMainWindow::CreateToolBars()
mToolsToolBar->setObjectName("ToolsToolbar");
insertToolBarBreak(mToolsToolBar);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_INSERT]);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_LIGHT]);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_POINT_LIGHT]);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SPOTLIGHT]);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_DIRECTIONAL_LIGHT]);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_AREA_LIGHT]);
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_CAMERA]);
mToolsToolBar->addSeparator();
mToolsToolBar->addAction(mActions[LC_EDIT_ACTION_SELECT]);
@ -817,7 +831,7 @@ void lcMainWindow::TogglePreviewWidget(bool Visible)
else
mPreviewToolBar->hide();
}
else if (Visible)
else if (Visible)
{
CreatePreviewWidget();
}
@ -2887,62 +2901,62 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
case LC_PIECE_MOVE_PLUSX:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true);
break;
case LC_PIECE_MOVE_MINUSX:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(-lcMax(GetMoveXYSnap(), 0.1f), 0.0f, 0.0f)), true, false, true, true, true);
break;
case LC_PIECE_MOVE_PLUSY:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true);
break;
case LC_PIECE_MOVE_MINUSY:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetMoveXYSnap(), 0.1f), 0.0f)), true, false, true, true, true);
break;
case LC_PIECE_MOVE_PLUSZ:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true);
break;
case LC_PIECE_MOVE_MINUSZ:
if (ActiveModel)
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true);
ActiveModel->MoveSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetMoveZSnap(), 0.1f))), true, false, true, true, true);
break;
case LC_PIECE_ROTATE_PLUSX:
if (ActiveModel)
ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true);
break;
case LC_PIECE_ROTATE_MINUSX:
if (ActiveModel)
ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(-lcVector3(lcMax(GetAngleSnap(), 1.0f), 0.0f, 0.0f)), true, false, true, true);
break;
case LC_PIECE_ROTATE_PLUSY:
if (ActiveModel)
ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true);
break;
case LC_PIECE_ROTATE_MINUSY:
if (ActiveModel)
ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, -lcMax(GetAngleSnap(), 1.0f), 0.0f)), true, false, true, true);
break;
case LC_PIECE_ROTATE_PLUSZ:
if (ActiveModel)
ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, lcMax(GetAngleSnap(), 1.0f))), true, false, true, true);
break;
case LC_PIECE_ROTATE_MINUSZ:
if (ActiveModel)
ActiveModel->RotateSelectedPieces(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, true);
ActiveModel->RotateSelectedObjects(ActiveView->GetMoveDirection(lcVector3(0.0f, 0.0f, -lcMax(GetAngleSnap(), 1.0f))), true, false, true, true);
break;
case LC_PIECE_MINIFIG_WIZARD:
@ -3362,8 +3376,16 @@ void lcMainWindow::HandleCommand(lcCommandId CommandId)
SetTool(lcTool::Insert);
break;
case LC_EDIT_ACTION_LIGHT:
SetTool(lcTool::Light);
case LC_EDIT_ACTION_POINT_LIGHT:
SetTool(lcTool::PointLight);
break;
case LC_EDIT_ACTION_AREA_LIGHT:
SetTool(lcTool::AreaLight);
break;
case LC_EDIT_ACTION_DIRECTIONAL_LIGHT:
SetTool(lcTool::DirectionalLight);
break;
case LC_EDIT_ACTION_SPOTLIGHT:

View file

@ -51,6 +51,21 @@ inline T lcClamp(const T& Value, const T& Min, const T& Max)
return Value;
}
class lcVector2i
{
public:
lcVector2i()
{
}
constexpr lcVector2i(const int _x, const int _y)
: x(_x), y(_y)
{
}
int x, y;
};
class lcVector2
{
public:
@ -649,6 +664,11 @@ inline lcVector3 lcVector3FromColor(quint32 Color)
return v;
}
inline lcVector3 lcVector3FromQColor(QColor Color)
{
return lcVector3(Color.redF(), Color.greenF(), Color.blueF());
}
inline lcVector4 lcVector4FromColor(quint32 Color)
{
lcVector4 v(LC_RGBA_RED(Color), LC_RGBA_GREEN(Color), LC_RGBA_BLUE(Color), LC_RGBA_ALPHA(Color));
@ -661,6 +681,11 @@ inline quint32 lcColorFromVector3(const lcVector3& Color)
return LC_RGB(roundf(Color[0] * 255), roundf(Color[1] * 255), roundf(Color[2] * 255));
}
inline QColor lcQColorFromVector3(const lcVector3& Color)
{
return QColor::fromRgb(roundf(Color[0] * 255), roundf(Color[1] * 255), roundf(Color[2] * 255));
}
inline float lcLuminescence(const lcVector3& Color)
{
return 0.2126f * Color[0] + 0.7152f * Color[1] + 0.0722f * Color[2];
@ -1991,6 +2016,125 @@ inline bool lcSphereRayMinIntersectDistance(const lcVector3& Center, float Radiu
}
}
inline bool lcConeRayMinIntersectDistance(const lcVector3& Tip, const lcVector3& Direction, float Radius, float Height, const lcVector3& Start, const lcVector3& End, float* Dist)
{
const lcVector3 v = End - Start;
const lcVector3 h = Direction;
const lcVector3 w = Start - Tip;
const float vh = lcDot(v, h);
const float wh = lcDot(w, h);
const float m = (Radius * Radius) / (Height * Height);
const float a = lcDot(v, v) - m * vh * vh - vh * vh;
const float b = 2 * (lcDot(v, w) - m * vh * wh - vh * wh);
const float c = lcDot(w, w) - m * wh * wh - wh * wh;
const float delta = b * b - 4 * a * c;
if (delta < 0.0f)
return false;
float ts[2] = { (-b - sqrtf(delta)) / (2 * a), (-b + sqrtf(delta)) / (2 * a) };
for (int ti = 0; ti < 2; ti++)
{
float t = ts[ti];
lcVector3 Intersection = Start + v * t;
float ConeD = lcDot(Intersection - Tip, Direction);
if (ConeD < 0.0f)
continue;
if (ConeD < Height)
{
*Dist = lcLength(Intersection - Start);
return true;
}
lcVector3 Center(Tip + Direction * Height);
lcVector4 Plane(Direction, -lcDot(Direction, Center));
if (lcLineSegmentPlaneIntersection(&Intersection, Start, End, Plane))
{
if (lcLengthSquared(Center - Intersection) < Radius * Radius)
{
*Dist = lcLength(Intersection - Start);
return true;
}
}
}
return false;
}
inline bool lcCylinderRayMinIntersectDistance(float Radius, float Height, const lcVector3& Start, const lcVector3& End, float* Dist)
{
lcVector4 BottomPlane(0.0f, 0.0f, 1.0f, 0.0f);
lcVector3 Intersection;
float MinDistance = FLT_MAX;
if (lcLineSegmentPlaneIntersection(&Intersection, Start, End, BottomPlane))
{
if (Intersection.x * Intersection.x + Intersection.y * Intersection.y < Radius * Radius)
{
float Distance = lcLength(Intersection - Start);
if (Distance < MinDistance)
MinDistance = Distance;
}
}
lcVector4 TopPlane(0.0f, 0.0f, 1.0f, -Height);
if (lcLineSegmentPlaneIntersection(&Intersection, Start, End, TopPlane))
{
if (Intersection.x * Intersection.x + Intersection.y * Intersection.y < Radius * Radius)
{
float Distance = lcLength(Intersection - Start);
if (Distance < MinDistance)
MinDistance = Distance;
}
}
lcVector3 Direction = End - Start;
float a = (Direction.x * Direction.x) + (Direction.y * Direction.y);
float b = 2 * (Direction.x * Start.x + Direction.y * Start.y);
float c = (Start.x * Start.x) + (Start.y * Start.y) - (Radius * Radius);
float delta = b * b - 4 * (a * c);
if (delta > 0.0f)
{
float ts[2] = { (-b - sqrtf(delta)) / (2 * a), (-b + sqrtf(delta)) / (2 * a) };
for (int ti = 0; ti < 2; ti++)
{
float t = ts[ti];
Intersection = Start + Direction * t;
if (Intersection.z < 0.0f || Intersection.z > Height)
continue;
float Distance = lcLength(Intersection - Start);
if (Distance < MinDistance)
MinDistance = Distance;
}
}
if (MinDistance == FLT_MAX)
return false;
*Dist = MinDistance;
return true;
}
inline lcVector3 lcRayPointClosestPoint(const lcVector3& Point, const lcVector3& Start, const lcVector3& End)
{
const lcVector3 Dir = Point - Start;

View file

@ -305,14 +305,14 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal);
const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal);
sprintf(Line, " smooth_triangle { <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f> }\n",
sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n",
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
File.WriteLine(Line);
}
if (Section->ColorIndex != gDefaultColor)
{
sprintf(Line, "material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]);
sprintf(Line, " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]);
File.WriteLine(Line);
}

View file

@ -107,6 +107,86 @@ void lcModelProperties::ParseLDrawLine(QTextStream& Stream)
}
}
lcPOVRayOptions::lcPOVRayOptions() :
UseLGEO(false),
ExcludeFloor(false),
ExcludeBackground(false),
NoReflection(false),
NoShadow(false),
FloorAxis(1),
FloorAmbient(0.4f),
FloorDiffuse(0.4f),
FloorColor(0.8f,0.8f,0.8f)
{}
void lcPOVRayOptions::ParseLDrawLine(QTextStream& LineStream)
{
QString Token;
LineStream >> Token;
if (Token == QLatin1String("HEADER_INCLUDE_FILE"))
{
LineStream >> HeaderIncludeFile;
if (!QFileInfo(HeaderIncludeFile).isReadable())
HeaderIncludeFile.clear();
}
else if (Token == QLatin1String("FOOTER_INCLUDE_FILE"))
{
LineStream >> FooterIncludeFile;
if (!QFileInfo(FooterIncludeFile).isReadable())
FooterIncludeFile.clear();
}
else if (Token == QLatin1String("FLOOR_AXIS"))
{
LineStream >> FloorAxis;
if (FloorAxis < 0 || FloorAxis > 2)
FloorAxis = 1; // y
}
else if (Token == QLatin1String("FLOOR_COLOR_RGB"))
LineStream >> FloorColor[0] >> FloorColor[1] >> FloorColor[2];
else if (Token == QLatin1String("FLOOR_AMBIENT"))
LineStream >> FloorAmbient;
else if (Token == QLatin1String("FLOOR_DIFFUSE"))
LineStream >> FloorDiffuse;
else if (Token == QLatin1String("EXCLUDE_FLOOR"))
ExcludeFloor = true;
else if (Token == QLatin1String("EXCLUDE_BACKGROUND"))
ExcludeFloor = true;
else if (Token == QLatin1String("NO_REFLECTION"))
NoReflection = true;
else if (Token == QLatin1String("NO_SHADOWS"))
NoShadow = true;
else if (Token == QLatin1String("USE_LGEO"))
UseLGEO = true;
}
void lcPOVRayOptions::SaveLDraw(QTextStream& Stream) const
{
const QLatin1String LineEnding("\r\n");
if (!HeaderIncludeFile.isEmpty())
Stream << QLatin1String("0 !LEOCAD POV_RAY HEADER_INCLUDE_FILE ") << QDir::toNativeSeparators(HeaderIncludeFile) << LineEnding;
if (!FooterIncludeFile.isEmpty())
Stream << QLatin1String("0 !LEOCAD POV_RAY FOOTER_INCLUDE_FILE ") << QDir::toNativeSeparators(FooterIncludeFile) << LineEnding;
if (FloorAxis != 1)
Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_AXIS ") << FloorAxis << LineEnding;
if (FloorColor != lcVector3(0.8f,0.8f,0.8f))
Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_COLOR_RGB ") << FloorColor[0] << ' ' << FloorColor[1] << ' ' << FloorColor[2] << LineEnding;
if (FloorAmbient != 0.4f)
Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_AMBIENT ") << FloorAmbient << LineEnding;
if (FloorDiffuse != 0.4f)
Stream << QLatin1String("0 !LEOCAD POV_RAY FLOOR_DIFFUSE ") << FloorDiffuse << LineEnding;
if (ExcludeFloor)
Stream << QLatin1String("0 !LEOCAD POV_RAY EXCLUDE_FLOOR") << LineEnding;
if (ExcludeBackground)
Stream << QLatin1String("0 !LEOCAD POV_RAY EXCLUDE_BACKGROUND") << LineEnding;
if (NoReflection)
Stream << QLatin1String("0 !LEOCAD POV_RAY NO_REFLECTION") << LineEnding;
if (NoShadow)
Stream << QLatin1String("0 !LEOCAD POV_RAY NO_SHADOWS") << LineEnding;
if (UseLGEO)
Stream << QLatin1String("0 !LEOCAD POV_RAY USE_LGEO") << LineEnding;
}
lcModel::lcModel(const QString& FileName, Project* Project, bool Preview)
: mProject(Project), mIsPreview(Preview)
{
@ -540,7 +620,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project)
if (Token != QLatin1String("!LEOCAD"))
{
mFileLines.append(OriginalLine);
mFileLines.append(OriginalLine);
continue;
}
@ -571,6 +651,19 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project)
}
else if (Token == QLatin1String("LIGHT"))
{
if (!Light)
Light = new lcLight(lcVector3(0.0f, 0.0f, 0.0f), lcLightType::Point);
if (Light->ParseLDrawLine(LineStream))
{
Light->CreateName(mLights);
mLights.Add(Light);
Light = nullptr;
}
}
else if (Token == QLatin1String("POV_RAY"))
{
mPOVRayOptions.ParseLDrawLine(LineStream);
}
else if (Token == QLatin1String("GROUP"))
{
@ -641,7 +734,7 @@ void lcModel::LoadLDraw(QIODevice& Device, Project* Project)
if (Library->IsPrimitive(CleanId.constData()))
{
mFileLines.append(OriginalLine);
mFileLines.append(OriginalLine);
}
else
{
@ -946,7 +1039,7 @@ bool lcModel::LoadLDD(const QString& FileData)
{
std::vector<lcPiece*> Pieces;
std::vector<std::vector<lcPiece*>> Groups;
if (!lcImportLXFMLFile(FileData, Pieces, Groups))
return false;
@ -2131,8 +2224,14 @@ lcMatrix33 lcModel::GetRelativeRotation() const
{
const lcObject* Focus = GetFocusObject();
if (Focus && Focus->IsPiece())
return ((lcPiece*)Focus)->GetRelativeRotation();
if (Focus)
{
if (Focus->IsPiece())
return ((lcPiece*)Focus)->GetRelativeRotation();
if (Focus->IsLight())
return ((lcLight*)Focus)->GetRelativeRotation();
}
}
return lcMatrix33Identity();
@ -2606,7 +2705,7 @@ bool lcModel::RemoveSelectedObjects()
return RemovedPiece || RemovedCamera || RemovedLight;
}
void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint)
void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove)
{
bool Moved = false;
lcMatrix33 RelativeRotation;
@ -2667,7 +2766,7 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector
{
if (Light->IsSelected())
{
Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedObjectDistance);
Light->MoveSelected(mCurrentStep, gMainWindow->GetAddKeys(), TransformedObjectDistance, FirstMove);
Light->UpdatePosition(mCurrentStep);
Moved = true;
}
@ -2677,13 +2776,15 @@ void lcModel::MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector
if (Moved && Update)
{
UpdateAllViews();
if (Checkpoint)
SaveCheckpoint(tr("Moving"));
gMainWindow->UpdateSelectedObjects(false);
}
}
void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint)
void lcModel::RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint)
{
if (Angles.LengthSquared() < 0.001f)
return;
@ -2712,6 +2813,12 @@ void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool
}
else
{
int Flags;
lcArray<lcObject*> Selection;
lcObject* Focus;
GetSelectionInformation(&Flags, Selection, &Focus);
if (!gMainWindow->GetSeparateTransform())
{
lcVector3 Center;
@ -2729,42 +2836,78 @@ void lcModel::RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool
else
WorldToFocusMatrix = lcMatrix33Identity();
for (lcPiece* Piece : mPieces)
for (lcObject* Object : Selection)
{
if (!Piece->IsSelected())
continue;
if (Object->IsPiece())
{
lcPiece* Piece = (lcPiece*)Object;
Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Piece->UpdatePosition(mCurrentStep);
Rotated = true;
Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Piece->UpdatePosition(mCurrentStep);
Rotated = true;
}
else if (Object->IsLight())
{
lcLight* Light = (lcLight*)Object;
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Light->UpdatePosition(mCurrentStep);
Rotated = true;
}
}
}
else
{
for (lcPiece* Piece : mPieces)
for (lcObject* Object : Selection)
{
if (!Piece->IsSelected())
continue;
const lcVector3 Center = Piece->GetRotationCenter();
lcMatrix33 WorldToFocusMatrix;
lcMatrix33 RelativeRotationMatrix;
if (Relative)
if (Object->IsPiece())
{
const lcMatrix33 RelativeRotation = Piece->GetRelativeRotation();
WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation);
RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation);
}
else
{
WorldToFocusMatrix = lcMatrix33Identity();
RelativeRotationMatrix = RotationMatrix;
}
lcPiece* Piece = (lcPiece*)Object;
Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RelativeRotationMatrix, Center, WorldToFocusMatrix);
Piece->UpdatePosition(mCurrentStep);
Rotated = true;
const lcVector3 Center = Piece->GetRotationCenter();
lcMatrix33 WorldToFocusMatrix;
lcMatrix33 RelativeRotationMatrix;
if (Relative)
{
const lcMatrix33 RelativeRotation = Piece->GetRelativeRotation();
WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation);
RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation);
}
else
{
WorldToFocusMatrix = lcMatrix33Identity();
RelativeRotationMatrix = RotationMatrix;
}
Piece->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RelativeRotationMatrix, Center, WorldToFocusMatrix);
Piece->UpdatePosition(mCurrentStep);
Rotated = true;
}
else if (Object->IsLight())
{
lcLight* Light = (lcLight*)Object;
const lcVector3 Center = Light->GetRotationCenter();
lcMatrix33 WorldToFocusMatrix;
lcMatrix33 RelativeRotationMatrix;
if (Relative)
{
const lcMatrix33 RelativeRotation = Light->GetRelativeRotation();
WorldToFocusMatrix = lcMatrix33AffineInverse(RelativeRotation);
RelativeRotationMatrix = lcMul(RotationMatrix, RelativeRotation);
}
else
{
WorldToFocusMatrix = lcMatrix33Identity();
RelativeRotationMatrix = RotationMatrix;
}
Light->Rotate(mCurrentStep, gMainWindow->GetAddKeys(), RotationMatrix, Center, WorldToFocusMatrix);
Light->UpdatePosition(mCurrentStep);
Rotated = true;
}
}
}
}
@ -2810,19 +2953,19 @@ void lcModel::TransformSelectedObjects(lcTransformType TransformType, const lcVe
switch (TransformType)
{
case lcTransformType::AbsoluteTranslation:
MoveSelectedObjects(Transform, false, false, true, true);
MoveSelectedObjects(Transform, false, false, true, true, true);
break;
case lcTransformType::RelativeTranslation:
MoveSelectedObjects(Transform, true, false, true, true);
MoveSelectedObjects(Transform, true, false, true, true, true);
break;
case lcTransformType::AbsoluteRotation:
RotateSelectedPieces(Transform, false, false, true, true);
RotateSelectedObjects(Transform, false, false, true, true);
break;
case lcTransformType::RelativeRotation:
RotateSelectedPieces(Transform, true, false, true, true);
RotateSelectedObjects(Transform, true, false, true, true);
break;
case lcTransformType::Count:
@ -3011,6 +3154,147 @@ void lcModel::SetCameraName(lcCamera* Camera, const QString& Name)
gMainWindow->UpdateCameraMenu();
}
void lcModel::SetLightType(lcLight* Light, lcLightType LightType)
{
if (!Light->SetLightType(LightType))
return;
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Type"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightColor(lcLight* Light, const lcVector3& Color)
{
Light->SetColor(Color, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Color"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightAttenuationDistance(lcLight* Light, float Distance)
{
Light->SetAttenuationDistance(Distance, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Attenuation Distance"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightAttenuationPower(lcLight* Light, float Power)
{
Light->SetAttenuationPower(Power, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Attenuation Power"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetSpotLightConeAngle(lcLight* Light, float Angle)
{
Light->SetSpotConeAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Spot Light Cone Angle"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetSpotLightPenumbraAngle(lcLight* Light, float Angle)
{
Light->SetSpotPenumbraAngle(Angle, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Spot Light Penumbra Angle"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetSpotLightTightness(lcLight* Light, float Tightness)
{
Light->SetSpotTightness(Tightness, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Spot Light Tightness"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightAreaShape(lcLight* Light, lcLightAreaShape LightAreaShape)
{
if (!Light->SetAreaShape(LightAreaShape))
return;
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Area Light Shape"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightAreaGrid(lcLight* Light, lcVector2i AreaGrid)
{
if (!Light->SetAreaGrid(AreaGrid, mCurrentStep, gMainWindow->GetAddKeys()))
return;
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Area Light Size"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightSize(lcLight* Light, lcVector2 LightAreaSize)
{
Light->SetSize(LightAreaSize, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Size"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightPower(lcLight* Light, float Power)
{
Light->SetPower(Power, mCurrentStep, gMainWindow->GetAddKeys());
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Power"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightCastShadow(lcLight* Light, bool CastShadow)
{
if (!Light->SetCastShadow(CastShadow))
return;
Light->UpdatePosition(mCurrentStep);
SaveCheckpoint(tr("Changing Light Shadow"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
}
void lcModel::SetLightName(lcLight* Light, const QString &Name)
{
if (Light->GetName() == Name)
return;
Light->SetName(Name);
SaveCheckpoint(tr("Renaming Light"));
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
gMainWindow->UpdateCameraMenu();
}
bool lcModel::AnyPiecesSelected() const
{
for (const lcPiece* Piece : mPieces)
@ -3123,20 +3407,18 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota
if (!Light->IsSelected())
continue;
if (Light->IsFocused() && Relative)
if (Light->IsFocused())
{
Center = Light->GetSectionPosition(Light->GetFocusSection());
// RelativeRotation = Piece->GetRelativeRotation();
Center = Light->GetRotationCenter();
if (Relative)
RelativeRotation = Light->GetRelativeRotation();
return true;
}
Center += Light->GetSectionPosition(LC_LIGHT_SECTION_POSITION);
NumSelected++;
if (Light->IsSpotLight() || Light->IsDirectionalLight())
{
Center += Light->GetSectionPosition(LC_LIGHT_SECTION_TARGET);
NumSelected++;
}
}
if (NumSelected)
@ -3148,6 +3430,33 @@ bool lcModel::GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRota
return false;
}
bool lcModel::CanRotateSelection() const
{
int Flags;
lcArray<lcObject*> Selection;
lcObject* Focus;
GetSelectionInformation(&Flags, Selection, &Focus);
if (Flags & LC_SEL_PIECE)
{
if ((Flags & (LC_SEL_CAMERA | LC_SEL_LIGHT)) == 0)
return true;
}
if ((Flags & (LC_SEL_PIECE | LC_SEL_CAMERA)) == 0)
{
if (Focus && Focus->IsLight())
{
lcLight* Light = (lcLight*)Focus;
return (Light->GetAllowedTransforms() & LC_OBJECT_TRANSFORM_ROTATE_XYZ) != 0;
}
}
return false;
}
bool lcModel::GetPieceFocusOrSelectionCenter(lcVector3& Center) const
{
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX), Max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
@ -3422,7 +3731,7 @@ void lcModel::GetSelectionInformation(int* Flags, lcArray<lcObject*>& Selection,
if (Camera->IsSelected())
{
Selection.Add(Camera);
*Flags |= LC_SEL_SELECTED;
*Flags |= LC_SEL_SELECTED | LC_SEL_CAMERA;
if (Camera->IsFocused())
*Focus = Camera;
@ -3434,7 +3743,7 @@ void lcModel::GetSelectionInformation(int* Flags, lcArray<lcObject*>& Selection,
if (Light->IsSelected())
{
Selection.Add(Light);
*Flags |= LC_SEL_SELECTED;
*Flags |= LC_SEL_SELECTED | LC_SEL_LIGHT;
if (Light->IsFocused())
*Focus = Light;
@ -3940,6 +4249,7 @@ void lcModel::RedoAction()
void lcModel::BeginMouseTool()
{
mMouseToolDistance = lcVector3(0.0f, 0.0f, 0.0f);
mMouseToolFirstMove = true;
}
void lcModel::EndMouseTool(lcTool Tool, bool Accept)
@ -3954,11 +4264,10 @@ void lcModel::EndMouseTool(lcTool Tool, bool Accept)
switch (Tool)
{
case lcTool::Insert:
case lcTool::Light:
break;
case lcTool::PointLight:
case lcTool::SpotLight:
SaveCheckpoint(tr("New SpotLight"));
case lcTool::DirectionalLight:
case lcTool::AreaLight:
break;
case lcTool::Camera:
@ -4024,37 +4333,35 @@ void lcModel::InsertPieceToolClicked(const lcMatrix44& WorldMatrix)
SaveCheckpoint(tr("Insert"));
}
void lcModel::PointLightToolClicked(const lcVector3& Position)
void lcModel::InsertLightToolClicked(const lcVector3& Position, lcLightType LightType)
{
lcLight* Light = new lcLight(Position[0], Position[1], Position[2]);
lcLight* Light = new lcLight(Position, LightType);
Light->CreateName(mLights);
mLights.Add(Light);
ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_POSITION, false);
SaveCheckpoint(tr("New Light"));
}
void lcModel::BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target)
{
lcLight* Light = new lcLight(Position[0], Position[1], Position[2], Target[0], Target[1], Target[2]);
mLights.Add(Light);
switch (LightType)
{
case lcLightType::Point:
SaveCheckpoint(tr("New Point Light"));
break;
mMouseToolDistance = Target;
case lcLightType::Spot:
SaveCheckpoint(tr("New Spot Light"));
break;
ClearSelectionAndSetFocus(Light, LC_LIGHT_SECTION_TARGET, false);
}
case lcLightType::Directional:
SaveCheckpoint(tr("New Directional Light"));
break;
void lcModel::UpdateSpotLightTool(const lcVector3& Position)
{
lcLight* Light = mLights[mLights.GetSize() - 1];
case lcLightType::Area:
SaveCheckpoint(tr("New Area Light"));
break;
Light->MoveSelected(1, false, Position - mMouseToolDistance);
Light->UpdatePosition(1);
mMouseToolDistance = Position;
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
case lcLightType::Count:
break;
}
}
void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target)
@ -4064,6 +4371,7 @@ void lcModel::BeginCameraTool(const lcVector3& Position, const lcVector3& Target
mCameras.Add(Camera);
mMouseToolDistance = Position;
mMouseToolFirstMove = false;
ClearSelectionAndSetFocus(Camera, LC_CAMERA_SECTION_TARGET, false);
}
@ -4076,6 +4384,7 @@ void lcModel::UpdateCameraTool(const lcVector3& Position)
Camera->UpdatePosition(1);
mMouseToolDistance = Position;
mMouseToolFirstMove = false;
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
@ -4086,8 +4395,10 @@ void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool
const lcVector3 PieceDistance = SnapPosition(Distance) - SnapPosition(mMouseToolDistance);
const lcVector3 ObjectDistance = Distance - mMouseToolDistance;
MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, true, false);
MoveSelectedObjects(PieceDistance, ObjectDistance, AllowRelative, AlternateButtonDrag, true, false, mMouseToolFirstMove);
mMouseToolDistance = Distance;
mMouseToolFirstMove = false;
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
@ -4096,8 +4407,10 @@ void lcModel::UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool
void lcModel::UpdateRotateTool(const lcVector3& Angles, bool AlternateButtonDrag)
{
const lcVector3 Delta = SnapRotation(Angles) - SnapRotation(mMouseToolDistance);
RotateSelectedPieces(Delta, true, AlternateButtonDrag, false, false);
RotateSelectedObjects(Delta, true, AlternateButtonDrag, false, false);
mMouseToolDistance = Angles;
mMouseToolFirstMove = false;
gMainWindow->UpdateSelectedObjects(false);
UpdateAllViews();
@ -4347,7 +4660,7 @@ void lcModel::ShowArrayDialog()
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("No pieces selected."));
return;
}
lcArrayDialog Dialog(gMainWindow);
if (Dialog.exec() != QDialog::Accepted)

View file

@ -5,18 +5,20 @@
#include "lc_array.h"
#define LC_SEL_NO_PIECES 0x0001 // No pieces in model
#define LC_SEL_PIECE 0x0002 // At last 1 piece selected
#define LC_SEL_SELECTED 0x0004 // At last 1 object selected
#define LC_SEL_UNSELECTED 0x0008 // At least 1 piece unselected
#define LC_SEL_HIDDEN 0x0010 // At least one piece hidden
#define LC_SEL_HIDDEN_SELECTED 0x0020 // At least one piece selected is hidden
#define LC_SEL_VISIBLE_SELECTED 0x0040 // At least one piece selected is not hidden
#define LC_SEL_GROUPED 0x0080 // At least one piece selected is grouped
#define LC_SEL_FOCUS_GROUPED 0x0100 // Focused piece is grouped
#define LC_SEL_CAN_GROUP 0x0200 // Can make a new group
#define LC_SEL_MODEL_SELECTED 0x0400 // At least one model reference is selected
#define LC_SEL_CAN_ADD_CONTROL_POINT 0x0800 // Can add control points to focused piece
#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x1000 // Can remove control points from focused piece
#define LC_SEL_PIECE 0x0002 // At least 1 piece selected
#define LC_SEL_CAMERA 0x0004 // At least 1 camera selected
#define LC_SEL_LIGHT 0x0008 // At least 1 light selected
#define LC_SEL_SELECTED 0x0010 // At least 1 object selected
#define LC_SEL_UNSELECTED 0x0020 // At least 1 piece unselected
#define LC_SEL_HIDDEN 0x0040 // At least one piece hidden
#define LC_SEL_HIDDEN_SELECTED 0x0080 // At least one piece selected is hidden
#define LC_SEL_VISIBLE_SELECTED 0x0100 // At least one piece selected is not hidden
#define LC_SEL_GROUPED 0x0200 // At least one piece selected is grouped
#define LC_SEL_FOCUS_GROUPED 0x0400 // Focused piece is grouped
#define LC_SEL_CAN_GROUP 0x0800 // Can make a new group
#define LC_SEL_MODEL_SELECTED 0x1000 // At least one model reference is selected
#define LC_SEL_CAN_ADD_CONTROL_POINT 0x2000 // Can add control points to focused piece
#define LC_SEL_CAN_REMOVE_CONTROL_POINT 0x4000 // Can remove control points from focused piece
enum class lcSelectionMode
{
@ -67,6 +69,26 @@ public:
lcVector3 mAmbientColor;
};
class lcPOVRayOptions
{
public:
lcPOVRayOptions();
void ParseLDrawLine(QTextStream& LineStream);
void SaveLDraw(QTextStream& Stream) const;
bool UseLGEO;
bool ExcludeFloor;
bool ExcludeBackground;
bool NoReflection;
bool NoShadow;
int FloorAxis;
float FloorAmbient;
float FloorDiffuse;
lcVector3 FloorColor;
QString HeaderIncludeFile;
QString FooterIncludeFile;
};
struct lcModelHistoryEntry
{
QByteArray File;
@ -136,6 +158,11 @@ public:
return mProperties;
}
const lcPOVRayOptions& GetPOVRayOptions() const
{
return mPOVRayOptions;
}
void SetFileName(const QString& FileName)
{
if (mProperties.mModelName == mProperties.mFileName)
@ -254,6 +281,7 @@ public:
lcModel* GetFirstSelectedSubmodel() const;
void GetSubModels(lcArray<lcModel*>& SubModels) const;
bool GetMoveRotateTransform(lcVector3& Center, lcMatrix33& RelativeRotation) const;
bool CanRotateSelection() const;
bool GetPieceFocusOrSelectionCenter(lcVector3& Center) const;
lcVector3 GetSelectionOrModelCenter() const;
bool GetFocusPosition(lcVector3& Position) const;
@ -301,9 +329,7 @@ public:
void BeginMouseTool();
void EndMouseTool(lcTool Tool, bool Accept);
void InsertPieceToolClicked(const lcMatrix44& WorldMatrix);
void PointLightToolClicked(const lcVector3& Position);
void BeginSpotLightTool(const lcVector3& Position, const lcVector3& Target);
void UpdateSpotLightTool(const lcVector3& Position);
void InsertLightToolClicked(const lcVector3& Position, lcLightType LightType);
void BeginCameraTool(const lcVector3& Position, const lcVector3& Target);
void UpdateCameraTool(const lcVector3& Position);
void UpdateMoveTool(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag);
@ -322,13 +348,13 @@ public:
void ZoomExtents(lcCamera* Camera, float Aspect);
void Zoom(lcCamera* Camera, float Amount);
void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint)
void MoveSelectedObjects(const lcVector3& Distance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove)
{
MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint);
MoveSelectedObjects(Distance, Distance, AllowRelative, AlternateButtonDrag, Update, Checkpoint, FirstMove);
}
void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint);
void RotateSelectedPieces(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint);
void MoveSelectedObjects(const lcVector3& PieceDistance, const lcVector3& ObjectDistance, bool AllowRelative, bool AlternateButtonDrag, bool Update, bool Checkpoint, bool FirstMove);
void RotateSelectedObjects(const lcVector3& Angles, bool Relative, bool RotatePivotPoint, bool Update, bool Checkpoint);
void ScaleSelectedPieces(const float Scale, bool Update, bool Checkpoint);
void TransformSelectedObjects(lcTransformType TransformType, const lcVector3& Transform);
void SetSelectedPiecesColorIndex(int ColorIndex);
@ -342,6 +368,20 @@ public:
void SetCameraZFar(lcCamera* Camera, float ZFar);
void SetCameraName(lcCamera* Camera, const QString& Name);
void SetLightType(lcLight* Light, lcLightType LightType);
void SetLightColor(lcLight* Light, const lcVector3& Color);
void SetLightAttenuationDistance(lcLight* Light, float Distance);
void SetLightAttenuationPower(lcLight* Light, float Power);
void SetSpotLightConeAngle(lcLight* Light, float Angle);
void SetSpotLightPenumbraAngle(lcLight* Light, float Angle);
void SetSpotLightTightness(lcLight* Light, float Tightness);
void SetLightAreaShape(lcLight* Light, lcLightAreaShape LightAreaShape);
void SetLightAreaGrid(lcLight* Light, lcVector2i AreaGrid);
void SetLightSize(lcLight* Light, lcVector2 LightAreaSize);
void SetLightPower(lcLight* Light, float Power);
void SetLightCastShadow(lcLight* Light, bool CastShadow);
void SetLightName(lcLight* Light, const QString& Name);
void ShowPropertiesDialog();
void ShowSelectByNameDialog();
void ShowArrayDialog();
@ -363,6 +403,7 @@ protected:
void AddPiece(lcPiece* Piece);
void InsertPiece(lcPiece* Piece, int Index);
lcPOVRayOptions mPOVRayOptions;
lcModelProperties mProperties;
Project* const mProject;
PieceInfo* mPieceInfo;
@ -371,6 +412,7 @@ protected:
bool mActive;
lcStep mCurrentStep;
lcVector3 mMouseToolDistance;
bool mMouseToolFirstMove;
lcArray<lcPiece*> mPieces;
lcArray<lcCamera*> mCameras;

View file

@ -148,6 +148,7 @@ static lcProfileEntry gProfileEntries[LC_NUM_PROFILE_KEYS] =
lcProfileEntry("Blender", "LDrawConfigPath", ""), // LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH
lcProfileEntry("Blender", "Version", ""), // LC_PROFILE_BLENDER_VERSION
lcProfileEntry("Blender", "AddonVersion", ""), // LC_PROFILE_BLENDER_ADDON_VERSION
lcProfileEntry("Blender", "AddonVersionCheck", 1), // LC_PROFILE_BLENDER_ADDON_VERSION_CHECK
lcProfileEntry("Blender", "ImportModule", ""), // LC_PROFILE_BLENDER_IMPORT_MODULE
lcProfileEntry("Settgins", "PreviewViewSphereEnabled", 0), // LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED

View file

@ -94,6 +94,7 @@ enum LC_PROFILE_KEY
LC_PROFILE_BLENDER_LDRAW_CONFIG_PATH,
LC_PROFILE_BLENDER_VERSION,
LC_PROFILE_BLENDER_ADDON_VERSION,
LC_PROFILE_BLENDER_ADDON_VERSION_CHECK,
LC_PROFILE_BLENDER_IMPORT_MODULE,
LC_PROFILE_PREVIEW_VIEW_SPHERE_ENABLED,

View file

@ -3,6 +3,7 @@
#include "lc_viewwidget.h"
#include <stdlib.h>
#include "lc_mainwindow.h"
#include "light.h"
#include "camera.h"
#include "texfont.h"
#include "lc_texture.h"
@ -415,7 +416,7 @@ lcMatrix44 lcView::GetPieceInsertPosition(bool IgnoreSelected, PieceInfo* Info)
lcModel* ActiveModel = GetActiveModel();
lcPieceInfoRayTest PieceInfoRayTest = FindPieceInfoUnderPointer(IgnoreSelected);
if (PieceInfoRayTest.Info)
{
lcVector3 Position = PieceInfoRayTest.Plane;
@ -927,7 +928,7 @@ void lcView::OnDraw()
mViewManipulator->DrawSelectMove(mTrackButton, mTrackTool);
else if (GetCurrentTool() == lcTool::Move && mTrackButton != lcTrackButton::None)
mViewManipulator->DrawSelectMove(mTrackButton, mTrackTool);
else if ((Tool == lcTool::Rotate || (Tool == lcTool::Select && mTrackButton != lcTrackButton::None && mTrackTool >= lcTrackTool::RotateX && mTrackTool <= lcTrackTool::RotateXYZ)) && ActiveModel->AnyPiecesSelected())
else if ((Tool == lcTool::Rotate || (Tool == lcTool::Select && mTrackButton != lcTrackButton::None && mTrackTool >= lcTrackTool::RotateX && mTrackTool <= lcTrackTool::RotateXYZ)) && ActiveModel->CanRotateSelection())
mViewManipulator->DrawRotate(mTrackButton, mTrackTool);
else if ((mTrackTool == lcTrackTool::Select || mTrackTool == lcTrackTool::ZoomRegion) && mTrackButton != lcTrackButton::None)
DrawSelectZoomRegionOverlay();
@ -1361,7 +1362,7 @@ void lcView::DrawRotateViewOverlay()
mContext->SetVertexBufferPointer(Verts);
mContext->SetVertexFormatPosition(2);
GLushort Indices[64 + 32] =
GLushort Indices[64 + 32] =
{
0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, 0,
@ -1594,21 +1595,23 @@ lcTrackTool lcView::GetOverrideTrackTool(Qt::MouseButton Button) const
constexpr lcTrackTool TrackToolFromTool[] =
{
lcTrackTool::Insert, // lcTool::Insert
lcTrackTool::PointLight, // lcTool::Light
lcTrackTool::SpotLight, // lcTool::SpotLight
lcTrackTool::Camera, // lcTool::Camera
lcTrackTool::Select, // lcTool::Select
lcTrackTool::MoveXYZ, // lcTool::Move
lcTrackTool::RotateXYZ, // lcTool::Rotate
lcTrackTool::Eraser, // lcTool::Eraser
lcTrackTool::Paint, // lcTool::Paint
lcTrackTool::ColorPicker, // lcTool::ColorPicker
lcTrackTool::Zoom, // lcTool::Zoom
lcTrackTool::Pan, // lcTool::Pan
lcTrackTool::OrbitXY, // lcTool::RotateView
lcTrackTool::Roll, // lcTool::Roll
lcTrackTool::ZoomRegion // lcTool::ZoomRegion
lcTrackTool::Insert, // lcTool::Insert
lcTrackTool::PointLight, // lcTool::PointLight
lcTrackTool::SpotLight, // lcTool::SpotLight
lcTrackTool::DirectionalLight, // lcTool::DirectionalLight
lcTrackTool::AreaLight, // lcTool::AreaLight
lcTrackTool::Camera, // lcTool::Camera
lcTrackTool::Select, // lcTool::Select
lcTrackTool::MoveXYZ, // lcTool::Move
lcTrackTool::RotateXYZ, // lcTool::Rotate
lcTrackTool::Eraser, // lcTool::Eraser
lcTrackTool::Paint, // lcTool::Paint
lcTrackTool::ColorPicker, // lcTool::ColorPicker
lcTrackTool::Zoom, // lcTool::Zoom
lcTrackTool::Pan, // lcTool::Pan
lcTrackTool::OrbitXY, // lcTool::RotateView
lcTrackTool::Roll, // lcTool::Roll
lcTrackTool::ZoomRegion // lcTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(TrackToolFromTool, lcTool::Count);
@ -1864,36 +1867,38 @@ lcCursor lcView::GetCursor() const
constexpr lcCursor CursorFromTrackTool[] =
{
lcCursor::Select, // lcTrackTool::None
lcCursor::Brick, // lcTrackTool::Insert
lcCursor::Light, // lcTrackTool::PointLight
lcCursor::Spotlight, // lcTrackTool::SpotLight
lcCursor::Camera, // lcTrackTool::Camera
lcCursor::Select, // lcTrackTool::Select
lcCursor::Move, // lcTrackTool::MoveX
lcCursor::Move, // lcTrackTool::MoveY
lcCursor::Move, // lcTrackTool::MoveZ
lcCursor::Move, // lcTrackTool::MoveXY
lcCursor::Move, // lcTrackTool::MoveXZ
lcCursor::Move, // lcTrackTool::MoveYZ
lcCursor::Move, // lcTrackTool::MoveXYZ
lcCursor::Rotate, // lcTrackTool::RotateX
lcCursor::Rotate, // lcTrackTool::RotateY
lcCursor::Rotate, // lcTrackTool::RotateZ
lcCursor::Rotate, // lcTrackTool::RotateXY
lcCursor::Rotate, // lcTrackTool::RotateXYZ
lcCursor::Move, // lcTrackTool::ScalePlus
lcCursor::Move, // lcTrackTool::ScaleMinus
lcCursor::Delete, // lcTrackTool::Eraser
lcCursor::Paint, // lcTrackTool::Paint
lcCursor::ColorPicker, // lcTrackTool::ColorPicker
lcCursor::Zoom, // lcTrackTool::Zoom
lcCursor::Pan, // lcTrackTool::Pan
lcCursor::RotateX, // lcTrackTool::OrbitX
lcCursor::RotateY, // lcTrackTool::OrbitY
lcCursor::RotateView, // lcTrackTool::OrbitXY
lcCursor::Roll, // lcTrackTool::Roll
lcCursor::ZoomRegion // lcTrackTool::ZoomRegion
lcCursor::Select, // lcTrackTool::None
lcCursor::Brick, // lcTrackTool::Insert
lcCursor::PointLight, // lcTrackTool::PointLight
lcCursor::SpotLight, // lcTrackTool::SpotLight
lcCursor::DirectionalLight, // lcTrackTool::DirectionalLight
lcCursor::AreaLight, // lcTrackTool::AreaLight
lcCursor::Camera, // lcTrackTool::Camera
lcCursor::Select, // lcTrackTool::Select
lcCursor::Move, // lcTrackTool::MoveX
lcCursor::Move, // lcTrackTool::MoveY
lcCursor::Move, // lcTrackTool::MoveZ
lcCursor::Move, // lcTrackTool::MoveXY
lcCursor::Move, // lcTrackTool::MoveXZ
lcCursor::Move, // lcTrackTool::MoveYZ
lcCursor::Move, // lcTrackTool::MoveXYZ
lcCursor::Rotate, // lcTrackTool::RotateX
lcCursor::Rotate, // lcTrackTool::RotateY
lcCursor::Rotate, // lcTrackTool::RotateZ
lcCursor::Rotate, // lcTrackTool::RotateXY
lcCursor::Rotate, // lcTrackTool::RotateXYZ
lcCursor::Move, // lcTrackTool::ScalePlus
lcCursor::Move, // lcTrackTool::ScaleMinus
lcCursor::Delete, // lcTrackTool::Eraser
lcCursor::Paint, // lcTrackTool::Paint
lcCursor::ColorPicker, // lcTrackTool::ColorPicker
lcCursor::Zoom, // lcTrackTool::Zoom
lcCursor::Pan, // lcTrackTool::Pan
lcCursor::RotateX, // lcTrackTool::OrbitX
lcCursor::RotateY, // lcTrackTool::OrbitY
lcCursor::RotateView, // lcTrackTool::OrbitXY
lcCursor::Roll, // lcTrackTool::Roll
lcCursor::ZoomRegion // lcTrackTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(CursorFromTrackTool, lcTrackTool::Count);
@ -1920,8 +1925,10 @@ void lcView::SetCursor(lcCursor CursorType)
{ 0, 0, "" }, // lcCursor::Hidden
{ 0, 0, "" }, // lcCursor::Default
{ 8, 3, ":/resources/cursor_insert" }, // lcCursor::Brick
{ 15, 15, ":/resources/cursor_light" }, // lcCursor::Light
{ 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::Spotlight
{ 15, 15, ":/resources/cursor_light" }, // lcCursor::PointLight
{ 7, 10, ":/resources/cursor_spotlight" }, // lcCursor::SpotLight
{ 15, 15, ":/resources/cursor_sunlight" }, // lcCursor::DirectionalLight
{ 15, 15, ":/resources/cursor_arealight" }, // lcCursor::AreaLight
{ 15, 9, ":/resources/cursor_camera" }, // lcCursor::Camera
{ 0, 2, ":/resources/cursor_select" }, // lcCursor::Select
{ 0, 2, ":/resources/cursor_select_add" }, // lcCursor::SelectAdd
@ -1969,36 +1976,38 @@ lcTool lcView::GetCurrentTool() const
{
constexpr lcTool ToolFromTrackTool[] =
{
lcTool::Select, // lcTrackTool::None
lcTool::Insert, // lcTrackTool::Insert
lcTool::Light, // lcTrackTool::PointLight
lcTool::SpotLight, // lcTrackTool::SpotLight
lcTool::Camera, // lcTrackTool::Camera
lcTool::Select, // lcTrackTool::Select
lcTool::Move, // lcTrackTool::MoveX
lcTool::Move, // lcTrackTool::MoveY
lcTool::Move, // lcTrackTool::MoveZ
lcTool::Move, // lcTrackTool::MoveXY
lcTool::Move, // lcTrackTool::MoveXZ
lcTool::Move, // lcTrackTool::MoveYZ
lcTool::Move, // lcTrackTool::MoveXYZ
lcTool::Rotate, // lcTrackTool::RotateX
lcTool::Rotate, // lcTrackTool::RotateY
lcTool::Rotate, // lcTrackTool::RotateZ
lcTool::Rotate, // lcTrackTool::RotateXY
lcTool::Rotate, // lcTrackTool::RotateXYZ
lcTool::Move, // lcTrackTool::ScalePlus
lcTool::Move, // lcTrackTool::ScaleMinus
lcTool::Eraser, // lcTrackTool::Eraser
lcTool::Paint, // lcTrackTool::Paint
lcTool::ColorPicker, // lcTrackTool::ColorPicker
lcTool::Zoom, // lcTrackTool::Zoom
lcTool::Pan, // lcTrackTool::Pan
lcTool::RotateView, // lcTrackTool::OrbitX
lcTool::RotateView, // lcTrackTool::OrbitY
lcTool::RotateView, // lcTrackTool::OrbitXY
lcTool::Roll, // lcTrackTool::Roll
lcTool::ZoomRegion // lcTrackTool::ZoomRegion
lcTool::Select, // lcTrackTool::None
lcTool::Insert, // lcTrackTool::Insert
lcTool::PointLight, // lcTrackTool::PointLight
lcTool::SpotLight, // lcTrackTool::SpotLight
lcTool::DirectionalLight, // lcTrackTool::DirectionalLight
lcTool::AreaLight, // lcTrackTool::AreaLight
lcTool::Camera, // lcTrackTool::Camera
lcTool::Select, // lcTrackTool::Select
lcTool::Move, // lcTrackTool::MoveX
lcTool::Move, // lcTrackTool::MoveY
lcTool::Move, // lcTrackTool::MoveZ
lcTool::Move, // lcTrackTool::MoveXY
lcTool::Move, // lcTrackTool::MoveXZ
lcTool::Move, // lcTrackTool::MoveYZ
lcTool::Move, // lcTrackTool::MoveXYZ
lcTool::Rotate, // lcTrackTool::RotateX
lcTool::Rotate, // lcTrackTool::RotateY
lcTool::Rotate, // lcTrackTool::RotateZ
lcTool::Rotate, // lcTrackTool::RotateXY
lcTool::Rotate, // lcTrackTool::RotateXYZ
lcTool::Move, // lcTrackTool::ScalePlus
lcTool::Move, // lcTrackTool::ScaleMinus
lcTool::Eraser, // lcTrackTool::Eraser
lcTool::Paint, // lcTrackTool::Paint
lcTool::ColorPicker, // lcTrackTool::ColorPicker
lcTool::Zoom, // lcTrackTool::Zoom
lcTool::Pan, // lcTrackTool::Pan
lcTool::RotateView, // lcTrackTool::OrbitX
lcTool::RotateView, // lcTrackTool::OrbitY
lcTool::RotateView, // lcTrackTool::OrbitXY
lcTool::Roll, // lcTrackTool::Roll
lcTool::ZoomRegion // lcTrackTool::ZoomRegion
};
LC_ARRAY_SIZE_CHECK(ToolFromTrackTool, lcTrackTool::Count);
@ -2032,7 +2041,7 @@ void lcView::UpdateTrackTool()
NewTrackTool = lcTrackTool::Insert;
break;
case lcTool::Light:
case lcTool::PointLight:
NewTrackTool = lcTrackTool::PointLight;
break;
@ -2040,6 +2049,14 @@ void lcView::UpdateTrackTool()
NewTrackTool = lcTrackTool::SpotLight;
break;
case lcTool::DirectionalLight:
NewTrackTool = lcTrackTool::DirectionalLight;
break;
case lcTool::AreaLight:
NewTrackTool = lcTrackTool::AreaLight;
break;
case lcTool::Camera:
NewTrackTool = lcTrackTool::Camera;
break;
@ -2258,16 +2275,11 @@ void lcView::StartTracking(lcTrackButton TrackButton)
switch (Tool)
{
case lcTool::Insert:
case lcTool::Light:
break;
case lcTool::PointLight:
case lcTool::SpotLight:
{
lcVector3 Position = GetCameraLightInsertPosition();
lcVector3 Target = Position + lcVector3(0.1f, 0.1f, 0.1f);
ActiveModel->BeginSpotLightTool(Position, Target);
}
break;
case lcTool::DirectionalLight:
case lcTool::AreaLight:
break;
case lcTool::Camera:
{
@ -2322,10 +2334,12 @@ void lcView::StopTracking(bool Accept)
switch (Tool)
{
case lcTool::Insert:
case lcTool::Light:
case lcTool::PointLight:
break;
case lcTool::SpotLight:
case lcTool::DirectionalLight:
case lcTool::AreaLight:
case lcTool::Camera:
ActiveModel->EndMouseTool(Tool, Accept);
break;
@ -2418,6 +2432,17 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
lcModel* ActiveModel = GetActiveModel();
mToolClicked = false;
auto AddLight = [this, ActiveModel](lcLightType LightType)
{
ActiveModel->InsertLightToolClicked(GetCameraLightInsertPosition(), LightType);
if ((mMouseModifiers & Qt::ControlModifier) == 0)
gMainWindow->SetTool(lcTool::Select);
mToolClicked = true;
UpdateTrackTool();
};
switch (mTrackTool)
{
case lcTrackTool::None:
@ -2441,22 +2466,25 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
break;
case lcTrackTool::PointLight:
{
ActiveModel->PointLightToolClicked(GetCameraLightInsertPosition());
if ((mMouseModifiers & Qt::ControlModifier) == 0)
gMainWindow->SetTool(lcTool::Select);
mToolClicked = true;
UpdateTrackTool();
}
AddLight(lcLightType::Point);
break;
case lcTrackTool::SpotLight:
AddLight(lcLightType::Spot);
break;
case lcTrackTool::DirectionalLight:
AddLight(lcLightType::Directional);
break;
case lcTrackTool::AreaLight:
AddLight(lcLightType::Area);
break;
case lcTrackTool::Camera:
StartTracking(TrackButton);
break;
case lcTrackTool::Select:
{
lcObjectSection ObjectSection = FindObjectUnderPointer(false, false);
@ -2488,7 +2516,7 @@ void lcView::OnButtonDown(lcTrackButton TrackButton)
case lcTrackTool::RotateZ:
case lcTrackTool::RotateXY:
case lcTrackTool::RotateXYZ:
if (ActiveModel->AnyPiecesSelected())
if (ActiveModel->CanRotateSelection())
StartTracking(TrackButton);
break;
@ -2687,10 +2715,9 @@ void lcView::OnMouseMove()
case lcTrackTool::None:
case lcTrackTool::Insert:
case lcTrackTool::PointLight:
break;
case lcTrackTool::SpotLight:
ActiveModel->UpdateSpotLightTool(GetCameraLightInsertPosition());
case lcTrackTool::DirectionalLight:
case lcTrackTool::AreaLight:
break;
case lcTrackTool::Camera:

View file

@ -17,8 +17,10 @@ enum class lcCursor
Hidden = First,
Default,
Brick,
Light,
Spotlight,
PointLight,
SpotLight,
DirectionalLight,
AreaLight,
Camera,
Select,
SelectAdd,
@ -52,6 +54,8 @@ enum class lcTrackTool
Insert,
PointLight,
SpotLight,
DirectionalLight,
AreaLight,
Camera,
Select,
MoveX,

View file

@ -675,6 +675,8 @@ bool lcViewManipulator::IsTrackToolAllowed(lcTrackTool TrackTool, quint32 Allowe
case lcTrackTool::Insert:
case lcTrackTool::PointLight:
case lcTrackTool::SpotLight:
case lcTrackTool::DirectionalLight:
case lcTrackTool::AreaLight:
case lcTrackTool::Camera:
case lcTrackTool::Select:
return true;
@ -793,7 +795,7 @@ lcTrackTool lcViewManipulator::UpdateSelectMove()
ControlPointIndex = Section - LC_PIECE_SECTION_CONTROL_POINT_FIRST;
}
quint32 AllowedTransforms = Focus ? Focus->GetAllowedTransforms() : LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z | LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z;
quint32 AllowedTransforms = Focus ? Focus->GetAllowedTransforms() : LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ;
for (int AxisIndex = 0; AxisIndex < 3; AxisIndex++)
{

File diff suppressed because it is too large Load diff

View file

@ -5,179 +5,207 @@
#define LC_LIGHT_HIDDEN 0x0001
#define LC_LIGHT_DISABLED 0x0002
#define LC_LIGHT_SPOT 0x0004
#define LC_LIGHT_DIRECTIONAL 0x0008
#define LC_LIGHT_POSITION_SELECTED 0x0010
#define LC_LIGHT_POSITION_FOCUSED 0x0020
#define LC_LIGHT_TARGET_SELECTED 0x0040
#define LC_LIGHT_TARGET_FOCUSED 0x0080
#define LC_LIGHT_SELECTION_MASK (LC_LIGHT_POSITION_SELECTED | LC_LIGHT_TARGET_SELECTED)
#define LC_LIGHT_FOCUS_MASK (LC_LIGHT_POSITION_FOCUSED | LC_LIGHT_TARGET_FOCUSED)
enum lcLightSection
enum lcLightSection : quint32
{
LC_LIGHT_SECTION_POSITION,
LC_LIGHT_SECTION_INVALID = ~0U,
LC_LIGHT_SECTION_POSITION = 0,
LC_LIGHT_SECTION_TARGET
};
enum class lcLightType
{
Point,
Spot,
Directional,
Area,
Count
};
enum class lcLightAreaShape
{
Rectangle,
Square,
Disk,
Ellipse,
Count
};
class lcLight : public lcObject
{
public:
lcLight(float px, float py, float pz);
lcLight(float px, float py, float pz, float tx, float ty, float tz);
~lcLight();
lcLight(const lcVector3& Position, lcLightType LightType);
virtual ~lcLight() = default;
lcLight(const lcLight&) = delete;
lcLight(lcLight&&) = delete;
lcLight& operator=(const lcLight&) = delete;
lcLight& operator=(lcLight&&) = delete;
static QString GetLightTypeString(lcLightType LightType);
static QString GetAreaShapeString(lcLightAreaShape LightAreaShape);
bool IsPointLight() const
{
return (mState & (LC_LIGHT_SPOT | LC_LIGHT_DIRECTIONAL)) == 0;
return mLightType == lcLightType::Point;
}
bool IsSpotLight() const
{
return (mState & LC_LIGHT_SPOT) != 0;
return mLightType == lcLightType::Spot;
}
bool IsDirectionalLight() const
{
return (mState & LC_LIGHT_DIRECTIONAL) != 0;
return mLightType == lcLightType::Directional;
}
bool IsAreaLight() const
{
return mLightType == lcLightType::Area;
}
lcLightType GetLightType() const
{
return mLightType;
}
bool SetLightType(lcLightType LightType);
bool IsSelected() const override
{
return (mState & LC_LIGHT_SELECTION_MASK) != 0;
return mSelected;
}
bool IsSelected(quint32 Section) const override
{
switch (Section)
{
case LC_LIGHT_SECTION_POSITION:
return (mState & LC_LIGHT_POSITION_SELECTED) != 0;
break;
Q_UNUSED(Section);
case LC_LIGHT_SECTION_TARGET:
return (mState & LC_LIGHT_TARGET_SELECTED) != 0;
break;
}
return false;
return mSelected;
}
void SetSelected(bool Selected) override
{
if (Selected)
{
if (IsPointLight())
mState |= LC_LIGHT_POSITION_SELECTED;
else
mState |= LC_LIGHT_SELECTION_MASK;
}
else
mState &= ~(LC_LIGHT_SELECTION_MASK | LC_LIGHT_FOCUS_MASK);
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_LIGHT_SECTION_INVALID;
}
void SetSelected(quint32 Section, bool Selected) override
{
switch (Section)
{
case LC_LIGHT_SECTION_POSITION:
if (Selected)
mState |= LC_LIGHT_POSITION_SELECTED;
else
mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED);
break;
Q_UNUSED(Section);
case LC_LIGHT_SECTION_TARGET:
if (Selected)
{
if (!IsPointLight())
mState |= LC_LIGHT_TARGET_SELECTED;
}
else
mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED);
break;
}
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_LIGHT_SECTION_INVALID;
}
bool IsFocused() const override
{
return (mState & LC_LIGHT_FOCUS_MASK) != 0;
return mFocusedSection != LC_LIGHT_SECTION_INVALID;
}
bool IsFocused(quint32 Section) const override
{
switch (Section)
{
case LC_LIGHT_SECTION_POSITION:
return (mState & LC_LIGHT_POSITION_FOCUSED) != 0;
break;
case LC_LIGHT_SECTION_TARGET:
return (mState & LC_LIGHT_TARGET_FOCUSED) != 0;
break;
}
return false;
return mFocusedSection == Section;
}
void SetFocused(quint32 Section, bool Focused) override
{
switch (Section)
if (Focused)
{
case LC_LIGHT_SECTION_POSITION:
if (Focused)
mState |= LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED;
else
mState &= ~(LC_LIGHT_POSITION_SELECTED | LC_LIGHT_POSITION_FOCUSED);
break;
case LC_LIGHT_SECTION_TARGET:
if (Focused)
{
if (!IsPointLight())
mState |= LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED;
}
else
mState &= ~(LC_LIGHT_TARGET_SELECTED | LC_LIGHT_TARGET_FOCUSED);
break;
mFocusedSection = Section;
mSelected = true;
}
else
mFocusedSection = LC_LIGHT_SECTION_INVALID;
}
quint32 GetFocusSection() const override
{
if (mState & LC_LIGHT_POSITION_FOCUSED)
return LC_LIGHT_SECTION_POSITION;
if (!IsPointLight() && (mState & LC_LIGHT_TARGET_FOCUSED))
return LC_LIGHT_SECTION_TARGET;
return ~0U;
return mFocusedSection;
}
quint32 GetAllowedTransforms() const override
{
return LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z;
if (IsPointLight())
return LC_OBJECT_TRANSFORM_MOVE_XYZ;
const quint32 Section = GetFocusSection();
if (Section == LC_LIGHT_SECTION_POSITION || Section == LC_LIGHT_SECTION_INVALID)
return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ;
if (Section == LC_LIGHT_SECTION_TARGET)
return LC_OBJECT_TRANSFORM_MOVE_XYZ;
return 0;
}
lcMatrix33 GetRelativeRotation() const
{
const quint32 Section = GetFocusSection();
if (Section == LC_LIGHT_SECTION_POSITION)
return lcMatrix33(mWorldMatrix);
else
return lcMatrix33Identity();
}
lcVector3 GetSectionPosition(quint32 Section) const override
{
switch (Section)
{
case LC_LIGHT_SECTION_POSITION:
return mPosition;
if (Section == LC_LIGHT_SECTION_POSITION)
return mWorldMatrix.GetTranslation();
case LC_LIGHT_SECTION_TARGET:
return mTargetPosition;
}
if (Section == LC_LIGHT_SECTION_TARGET)
return lcMul31(lcVector3(0.0f, 0.0f, -mTargetDistance), mWorldMatrix);
return lcVector3(0.0f, 0.0f, 0.0f);
}
void SetPosition(const lcVector3& Position, lcStep Step, bool AddKey)
{
mPositionKeys.ChangeKey(Position, Step, AddKey);
}
void SetRotation(const lcMatrix33& Rotation, lcStep Step, bool AddKey)
{
mRotationKeys.ChangeKey(Rotation, Step, AddKey);
}
lcVector3 GetRotationCenter() const
{
const quint32 Section = GetFocusSection();
if (Section == LC_LIGHT_SECTION_POSITION || Section == LC_LIGHT_SECTION_INVALID)
{
return mWorldMatrix.GetTranslation();
}
else
{
return lcMul31(lcVector3(0.0f, 0.0f, -mTargetDistance), mWorldMatrix);
}
}
lcVector3 GetPosition() const
{
return mWorldMatrix.GetTranslation();
}
lcVector3 GetDirection() const
{
return -lcVector3(mWorldMatrix[2]);
}
const lcMatrix44& GetWorldMatrix() const
{
return mWorldMatrix;
}
void SaveLDraw(QTextStream& Stream) const;
bool ParseLDrawLine(QTextStream& Stream);
public:
void RayTest(lcObjectRayTest& ObjectRayTest) const override;
@ -189,7 +217,91 @@ public:
void RemoveTime(lcStep Start, lcStep Time);
bool IsVisible() const
{ return (mState & LC_LIGHT_HIDDEN) == 0; }
{
return (mState & LC_LIGHT_HIDDEN) == 0;
}
void SetColor(const lcVector3& Color, lcStep Step, bool AddKey);
lcVector3 GetColor() const
{
return mColor;
}
void SetAttenuationDistance(float Distance, lcStep Step, bool AddKey);
float GetAttenuationDistance() const
{
return mAttenuationDistance;
}
void SetAttenuationPower(float Power, lcStep Step, bool AddKey);
float GetAttenuationPower() const
{
return mAttenuationPower;
}
void SetSpotConeAngle(float Angle, lcStep Step, bool AddKey);
float GetSpotConeAngle() const
{
return mSpotConeAngle;
}
void SetSpotPenumbraAngle(float Angle, lcStep Step, bool AddKey);
float GetSpotPenumbraAngle() const
{
return mSpotPenumbraAngle;
}
void SetSpotTightness(float Angle, lcStep Step, bool AddKey);
float GetSpotTightness() const
{
return mSpotTightness;
}
bool SetAreaShape(lcLightAreaShape LightAreaShape);
lcLightAreaShape GetAreaShape() const
{
return mAreaShape;
}
bool SetAreaGrid(lcVector2i AreaGrid, lcStep Step, bool AddKey);
lcVector2i GetAreaGrid() const
{
return mAreaGrid;
}
void SetSize(lcVector2 Size, lcStep Step, bool AddKey);
lcVector2 GetSize() const
{
return mSize;
}
void SetPower(float Power, lcStep Step, bool AddKey);
float GetPower() const
{
return mPower;
}
bool SetCastShadow(bool CastShadow);
bool GetCastShadow() const
{
return mCastShadow;
}
void SetName(const QString& Name)
{
mName = Name;
}
QString GetName() const override
{
@ -198,36 +310,57 @@ public:
void CompareBoundingBox(lcVector3& Min, lcVector3& Max);
void UpdatePosition(lcStep Step);
void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance, bool FirstMove);
void Rotate(lcStep Step, bool AddKey, const lcMatrix33& RotationMatrix, const lcVector3& Center, const lcMatrix33& RotationFrame);
bool Setup(int LightIndex);
void CreateName(const lcArray<lcLight*>& Lights);
// Temporary parameters
lcMatrix44 mWorldLight;
lcVector3 mPosition;
lcVector3 mTargetPosition;
lcVector4 mAmbientColor;
lcVector4 mDiffuseColor;
lcVector4 mSpecularColor;
lcVector3 mAttenuation;
float mSpotCutoff;
float mSpotExponent;
lcMatrix44 mWorldMatrix;
protected:
lcObjectKeyArray<lcVector3> mPositionKeys;
lcObjectKeyArray<lcVector3> mTargetPositionKeys;
lcObjectKeyArray<lcVector4> mAmbientColorKeys;
lcObjectKeyArray<lcVector4> mDiffuseColorKeys;
lcObjectKeyArray<lcVector4> mSpecularColorKeys;
lcObjectKeyArray<lcVector3> mAttenuationKeys;
lcObjectKeyArray<float> mSpotCutoffKeys;
lcObjectKeyArray<float> mSpotExponentKeys;
void Initialize(const lcVector3& Position, const lcVector3& TargetPosition);
void UpdateLightType();
void DrawPointLight(lcContext* Context) const;
void DrawSpotLight(lcContext* Context) const;
void DrawDirectionalLight(lcContext* Context) const;
void DrawAreaLight(lcContext* Context) const;
void SetupLightMatrix(lcContext* Context) const;
void DrawSphere(lcContext* Context, const lcVector3& Center, float Radius) const;
void DrawCylinder(lcContext* Context, float Radius, float Height) const;
void DrawTarget(lcContext* Context) const;
void DrawCone(lcContext* Context, float TargetDistance) const;
QString mName;
quint32 mState;
lcLightType mLightType = lcLightType::Point;
bool mCastShadow = true;
lcVector3 mColor = lcVector3(1.0f, 1.0f, 1.0f);
lcVector2 mSize = lcVector2(0.0f, 0.0f);
float mPower = 1.0f;
float mAttenuationDistance = 0.0f;
float mAttenuationPower = 0.0f;
float mSpotConeAngle = 80.0f;
float mSpotPenumbraAngle = 0.0f;
float mSpotTightness = 0.0f;
lcLightAreaShape mAreaShape = lcLightAreaShape::Rectangle;
lcVector2i mAreaGrid = lcVector2i(2, 2);
quint32 mState = 0;
bool mSelected = false;
quint32 mFocusedSection = LC_LIGHT_SECTION_INVALID;
lcVector3 mTargetMovePosition = lcVector3(0.0f, 0.0f, 0.0f);
lcObjectKeyArray<lcVector3> mPositionKeys;
lcObjectKeyArray<lcMatrix33> mRotationKeys;
lcObjectKeyArray<lcVector3> mColorKeys;
lcObjectKeyArray<lcVector2> mSizeKeys;
lcObjectKeyArray<float> mPowerKeys;
lcObjectKeyArray<float> mAttenuationDistanceKeys;
lcObjectKeyArray<float> mAttenuationPowerKeys;
lcObjectKeyArray<float> mSpotConeAngleKeys;
lcObjectKeyArray<float> mSpotPenumbraAngleKeys;
lcObjectKeyArray<float> mSpotTightnessKeys;
lcObjectKeyArray<lcVector2i> mAreaGridKeys;
static constexpr float mTargetDistance = 50.0f;
};

View file

@ -1,6 +1,23 @@
#include "lc_global.h"
#include "object.h"
#define LC_OBJECT_ATTRIBUTE(T) \
template void lcObjectKeyArray<T>::SaveKeysLDraw(QTextStream& Stream, const char* ObjectName, const char* VariableName) const; \
template void lcObjectKeyArray<T>::LoadKeysLDraw(QTextStream& Stream); \
template const T& lcObjectKeyArray<T>::CalculateKey(lcStep Step) const; \
template void lcObjectKeyArray<T>::ChangeKey(const T& Value, lcStep Step, bool AddKey); \
template void lcObjectKeyArray<T>::InsertTime(lcStep Start, lcStep Time); \
template void lcObjectKeyArray<T>::RemoveTime(lcStep Start, lcStep Time); \
template void lcObject::SaveAttribute<T>(QTextStream& Stream, const T& Variable, const lcObjectKeyArray<T>& Keys, const char* ObjectName, const char* VariableName) const; \
template bool lcObject::LoadAttribute<T>(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray<T>& Keys, const char* VariableName)
LC_OBJECT_ATTRIBUTE(float);
LC_OBJECT_ATTRIBUTE(lcVector2i);
LC_OBJECT_ATTRIBUTE(lcVector2);
LC_OBJECT_ATTRIBUTE(lcVector3);
LC_OBJECT_ATTRIBUTE(lcVector4);
LC_OBJECT_ATTRIBUTE(lcMatrix33);
lcObject::lcObject(lcObjectType ObjectType)
: mObjectType(ObjectType)
{
@ -10,45 +27,32 @@ lcObject::~lcObject()
{
}
template void lcObjectKeyArray<float>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
template void lcObjectKeyArray<float>::LoadKeysLDraw(QTextStream& Stream);
template const float& lcObjectKeyArray<float>::CalculateKey(lcStep Step) const;
template void lcObjectKeyArray<float>::ChangeKey(const float& Value, lcStep Step, bool AddKey);
template void lcObjectKeyArray<float>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<float>::RemoveTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcVector3>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
template void lcObjectKeyArray<lcVector3>::LoadKeysLDraw(QTextStream& Stream);
template const lcVector3& lcObjectKeyArray<lcVector3>::CalculateKey(lcStep Step) const;
template void lcObjectKeyArray<lcVector3>::ChangeKey(const lcVector3& Value, lcStep Step, bool AddKey);
template void lcObjectKeyArray<lcVector3>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcVector3>::RemoveTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcVector4>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
template void lcObjectKeyArray<lcVector4>::LoadKeysLDraw(QTextStream& Stream);
template const lcVector4& lcObjectKeyArray<lcVector4>::CalculateKey(lcStep Step) const;
template void lcObjectKeyArray<lcVector4>::ChangeKey(const lcVector4& Value, lcStep Step, bool AddKey);
template void lcObjectKeyArray<lcVector4>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcVector4>::RemoveTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcMatrix33>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
template void lcObjectKeyArray<lcMatrix33>::LoadKeysLDraw(QTextStream& Stream);
template const lcMatrix33& lcObjectKeyArray<lcMatrix33>::CalculateKey(lcStep Step) const;
template void lcObjectKeyArray<lcMatrix33>::ChangeKey(const lcMatrix33& Value, lcStep Step, bool AddKey);
template void lcObjectKeyArray<lcMatrix33>::InsertTime(lcStep Start, lcStep Time);
template void lcObjectKeyArray<lcMatrix33>::RemoveTime(lcStep Start, lcStep Time);
template<typename T>
void lcObjectKeyArray<T>::SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const
static void SaveFloatValue(QTextStream& Stream, const T& Value)
{
constexpr int Count = sizeof(T) / sizeof(float);
for (int ValueIndex = 0; ValueIndex < Count; ValueIndex++)
Stream << ((const float*)&Value)[ValueIndex] << ' ';
}
template<typename T>
static void LoadFloatValue(QTextStream& Stream, T& Value)
{
constexpr int Count = sizeof(T) / sizeof(float);
for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++)
Stream >> ((float*)&Value)[ValueIdx];
}
template<typename T>
void lcObjectKeyArray<T>::SaveKeysLDraw(QTextStream& Stream, const char* ObjectName, const char* VariableName) const
{
for (const lcObjectKey<T>& Key : mKeys)
{
Stream << QLatin1String("0 !LEOCAD ") << KeyName << Key.Step << ' ';
Stream << QLatin1String("0 !LEOCAD ") << ObjectName << ' ' << VariableName << "_KEY " << Key.Step << ' ';
for (int ValueIdx = 0; ValueIdx < Count; ValueIdx++)
Stream << ((float*)&Key.Value)[ValueIdx] << ' ';
SaveFloatValue(Stream, Key.Value);
Stream << QLatin1String("\r\n");
}
@ -168,3 +172,39 @@ void lcObjectKeyArray<T>::RemoveTime(lcStep Start, lcStep Time)
KeyIt++;
}
}
template<typename T>
void lcObject::SaveAttribute(QTextStream& Stream, const T& Variable, const lcObjectKeyArray<T>& Keys, const char* ObjectName, const char* VariableName) const
{
if (Keys.GetSize() == 1)
{
Stream << QLatin1String("0 !LEOCAD ") << ObjectName << ' ' << VariableName << ' ';
SaveFloatValue(Stream, Variable);
Stream << QLatin1String("\r\n");
}
else
Keys.SaveKeysLDraw(Stream, ObjectName, VariableName);
}
template<typename T>
bool lcObject::LoadAttribute(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray<T>& Keys, const char* VariableName)
{
if (Token == VariableName)
{
LoadFloatValue(Stream, Variable);
Keys.ChangeKey(Variable, 1, true);
return true;
}
if (Token.endsWith(QLatin1String("_KEY")) && Token.leftRef(Token.size() - 4) == VariableName)
{
Keys.LoadKeysLDraw(Stream);
return true;
}
return false;
}

View file

@ -36,7 +36,7 @@ public:
mKeys.clear();
}
void SaveKeysLDraw(QTextStream& Stream, const char* KeyName) const;
void SaveKeysLDraw(QTextStream& Stream, const char* ObjectName, const char* VariableName) const;
void LoadKeysLDraw(QTextStream& Stream);
const T& CalculateKey(lcStep Step) const;
void ChangeKey(const T& Value, lcStep Step, bool AddKey);
@ -79,15 +79,18 @@ struct lcObjectBoxTest
lcArray<lcObject*> Objects;
};
#define LC_OBJECT_TRANSFORM_MOVE_X 0x001
#define LC_OBJECT_TRANSFORM_MOVE_Y 0x002
#define LC_OBJECT_TRANSFORM_MOVE_Z 0x004
#define LC_OBJECT_TRANSFORM_ROTATE_X 0x010
#define LC_OBJECT_TRANSFORM_ROTATE_Y 0x020
#define LC_OBJECT_TRANSFORM_ROTATE_Z 0x040
#define LC_OBJECT_TRANSFORM_SCALE_X 0x100
#define LC_OBJECT_TRANSFORM_SCALE_Y 0x200
#define LC_OBJECT_TRANSFORM_SCALE_Z 0x400
#define LC_OBJECT_TRANSFORM_MOVE_X 0x001
#define LC_OBJECT_TRANSFORM_MOVE_Y 0x002
#define LC_OBJECT_TRANSFORM_MOVE_Z 0x004
#define LC_OBJECT_TRANSFORM_MOVE_XYZ (LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z)
#define LC_OBJECT_TRANSFORM_ROTATE_X 0x010
#define LC_OBJECT_TRANSFORM_ROTATE_Y 0x020
#define LC_OBJECT_TRANSFORM_ROTATE_Z 0x040
#define LC_OBJECT_TRANSFORM_ROTATE_XYZ (LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z)
#define LC_OBJECT_TRANSFORM_SCALE_X 0x100
#define LC_OBJECT_TRANSFORM_SCALE_Y 0x200
#define LC_OBJECT_TRANSFORM_SCALE_Z 0x400
#define LC_OBJECT_TRANSFORM_SCALE_XYZ (LC_OBJECT_TRANSFORM_SCALE_X | LC_OBJECT_TRANSFORM_SCALE_Y | LC_OBJECT_TRANSFORM_SCALE_Z)
class lcObject
{
@ -138,7 +141,12 @@ public:
virtual void RemoveKeyFrames() = 0;
virtual QString GetName() const = 0;
protected:
template<typename T>
void SaveAttribute(QTextStream& Stream, const T& Variable, const lcObjectKeyArray<T>& Keys, const char* ObjectName, const char* VariableName) const;
template<typename T>
bool LoadAttribute(QTextStream& Stream, const QString& Token, T& Variable, lcObjectKeyArray<T>& Keys, const char* VariableName);
private:
lcObjectType mObjectType;
};

View file

@ -125,10 +125,10 @@ void lcPiece::SaveLDraw(QTextStream& Stream) const
}
if (mPositionKeys.GetSize() > 1)
mPositionKeys.SaveKeysLDraw(Stream, "PIECE POSITION_KEY ");
mPositionKeys.SaveKeysLDraw(Stream, "PIECE", "POSITION");
if (mRotationKeys.GetSize() > 1)
mRotationKeys.SaveKeysLDraw(Stream, "PIECE ROTATION_KEY ");
mRotationKeys.SaveKeysLDraw(Stream, "PIECE", "ROTATION");
Stream << "1 " << mColorCode << ' ';
@ -835,12 +835,10 @@ void lcPiece::RotatePivotPoint(const lcMatrix33& RotationMatrix)
quint32 lcPiece::GetAllowedTransforms() const
{
constexpr quint32 Move = LC_OBJECT_TRANSFORM_MOVE_X | LC_OBJECT_TRANSFORM_MOVE_Y | LC_OBJECT_TRANSFORM_MOVE_Z;
constexpr quint32 Rotate = LC_OBJECT_TRANSFORM_ROTATE_X | LC_OBJECT_TRANSFORM_ROTATE_Y | LC_OBJECT_TRANSFORM_ROTATE_Z;
const quint32 Section = GetFocusSection();
if (Section == LC_PIECE_SECTION_POSITION || Section == LC_PIECE_SECTION_INVALID)
return Move | Rotate;
return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ;
const lcSynthInfo* SynthInfo = mPieceInfo->GetSynthInfo();
@ -850,10 +848,10 @@ quint32 lcPiece::GetAllowedTransforms() const
return LC_OBJECT_TRANSFORM_MOVE_Z;
if (SynthInfo->IsCurve())
return Move | Rotate | LC_OBJECT_TRANSFORM_SCALE_X;
return LC_OBJECT_TRANSFORM_MOVE_XYZ | LC_OBJECT_TRANSFORM_ROTATE_XYZ | LC_OBJECT_TRANSFORM_SCALE_X;
if (SynthInfo->IsNondirectional())
return Move;
return LC_OBJECT_TRANSFORM_MOVE_XYZ;
}
return 0;

View file

@ -48,6 +48,7 @@ public:
void SetSelected(bool Selected) override
{
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_PIECE_SECTION_INVALID;
}
@ -57,6 +58,7 @@ public:
Q_UNUSED(Section);
mSelected = Selected;
if (!Selected)
mFocusedSection = LC_PIECE_SECTION_INVALID;
}

View file

@ -7,6 +7,7 @@
#include "project.h"
#include "lc_instructions.h"
#include "image.h"
#include "light.h"
#include "lc_mainwindow.h"
#include "lc_view.h"
#include "lc_library.h"
@ -1828,15 +1829,6 @@ bool Project::ExportPOVRay(const QString& FileName)
return false;
}
POVFile.WriteLine("#version 3.7;\n\nglobal_settings {\n assumed_gamma 1.0\n}\n\n");
char Line[1024];
lcPiecesLibrary* Library = lcGetPiecesLibrary();
std::map<const PieceInfo*, std::pair<char[LC_PIECE_NAME_LEN + 1], int>> PieceTable;
size_t NumColors = gColorList.size();
std::vector<std::array<char, LC_MAX_COLOR_NAME>> ColorTable(NumColors);
enum
{
LGEO_PIECE_LGEO = 0x01,
@ -1855,10 +1847,402 @@ bool Project::ExportPOVRay(const QString& FileName)
LGEO_COLOR_GLITTER = 0x40
};
QString LGEOPath; // todo: load lgeo from registry and make sure it still works
char Line[1024];
if (!LGEOPath.isEmpty())
sprintf(Line, "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n",
LC_VERSION_TEXT,
mModels[0]->GetProperties().mFileName.toLatin1().constData(),
QDateTime::currentDateTime().toString(Qt::ISODate).toLatin1().constData());
POVFile.WriteLine(Line);
POVFile.WriteLine("#version 3.7;\n\n");
POVFile.WriteLine("global_settings { assumed_gamma 1.0 }\n\n");
lcPiecesLibrary* Library = lcGetPiecesLibrary();
std::map<const PieceInfo*, std::pair<char[LC_PIECE_NAME_LEN + 1], int>> PieceTable;
size_t NumColors = gColorList.size();
std::vector<std::array<char, LC_MAX_COLOR_NAME>> LgeoColorTable(NumColors);
std::vector<std::array<char, LC_MAX_COLOR_NAME>> ColorTable(NumColors);
const lcArray<lcLight*> Lights = gMainWindow->GetActiveModel()->GetLights();
const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera();
const QString CameraName = QString(Camera->GetName()).replace(" ","_");
const lcVector3& Position = Camera->mPosition;
const lcVector3& Target = Camera->mTargetPosition;
const lcVector3& Up = Camera->mUpVector;
const lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor);
const lcPOVRayOptions& POVRayOptions = mModels[0]->GetPOVRayOptions();
const QString TopModelName = QString("LC_%1").arg(QString(mModels[0]->GetFileName()).replace(" ","_").replace(".","_dot_"));
const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH);
const bool UseLGEO = POVRayOptions.UseLGEO && !LGEOPath.isEmpty();
const int TopModelColorCode = 7;
QStringList ColorMacros, MaterialColors;
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX);
lcVector3 Max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
lcVector3 Points[8];
lcGetBoxCorners(ModelPart.Info->GetBoundingBox(), Points);
for (int PointIdx = 0; PointIdx < 8; PointIdx++)
{
lcVector3 Point = lcMul31(Points[PointIdx], ModelPart.WorldMatrix);
Min = lcMin(Point, Min);
Max = lcMax(Point, Max);
}
}
lcVector3 Center = (Min + Max) / 2.0f;
float Radius = (Max - Center).Length() / 25.0f;
Center = lcVector3(Center[1], Center[0], Center[2]) / 25.0f;
lcVector3 FloorColor = POVRayOptions.FloorColor;
float FloorAmbient = POVRayOptions.FloorAmbient;
float FloorDiffuse = POVRayOptions.FloorDiffuse;
char FloorLocation[32];
char FloorAxis[16];
if (POVRayOptions.FloorAxis == 0)
{
sprintf(FloorAxis, "x");
sprintf(FloorLocation, "MaxX");
}
else if (POVRayOptions.FloorAxis == 1)
{
sprintf(FloorAxis, "y");
sprintf(FloorLocation, "MaxY");
}
else
{
sprintf(FloorAxis, "z");
sprintf(FloorLocation, "MaxZ");
}
for (const lcLight* Light : Lights)
{
if (Light->GetLightType() == lcLightType::Area)
{
if (FloorColor == lcVector3(0.8f,0.8f,0.8f))
FloorColor = {1.0f,1.0f,1.0f};
if (FloorAmbient == 0.4f)
FloorAmbient = 0.0f;
if (FloorDiffuse == 0.4f)
FloorDiffuse = 0.9f;
break;
}
}
if (!POVRayOptions.HeaderIncludeFile.isEmpty())
{
sprintf(Line, "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData());
POVFile.WriteLine(Line);
}
sprintf(Line,
"#ifndef (MinX) #declare MinX = %g; #end\n"
"#ifndef (MinY) #declare MinY = %g; #end\n"
"#ifndef (MinZ) #declare MinZ = %g; #end\n"
"#ifndef (MaxX) #declare MaxX = %g; #end\n"
"#ifndef (MaxY) #declare MaxY = %g; #end\n"
"#ifndef (MaxZ) #declare MaxZ = %g; #end\n"
"#ifndef (CenterX) #declare CenterX = %g; #end\n"
"#ifndef (CenterY) #declare CenterY = %g; #end\n"
"#ifndef (CenterZ) #declare CenterZ = %g; #end\n"
"#ifndef (Center) #declare Center = <CenterX,CenterY,CenterZ>; #end\n"
"#ifndef (Radius) #declare Radius = %g; #end\n",
Min[0], Min[1], Min[2], Max[0], -Max[1], Max[2], Center[0], Center[1], Center[2], Radius);
POVFile.WriteLine(Line);
sprintf(Line,
"#ifndef (CameraSky) #declare CameraSky = <%g,%g,%g>; #end\n"
"#ifndef (CameraLocation) #declare CameraLocation = <%g, %g, %g>; #end\n"
"#ifndef (CameraTarget) #declare CameraTarget = <%g, %g, %g>; #end\n"
"#ifndef (CameraAngle) #declare CameraAngle = %g; #end\n",
Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy);
POVFile.WriteLine(Line);
sprintf(Line,
"#ifndef (BackgroundColor) #declare BackgroundColor = <%1g, %1g, %1g>; #end\n"
"#ifndef (Background) #declare Background = %s; #end\n",
BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], (POVRayOptions.ExcludeBackground ? "false" : "true"));
POVFile.WriteLine(Line);
sprintf(Line,
"#ifndef (FloorAxis) #declare FloorAxis = %s; #end\n"
"#ifndef (FloorLocation) #declare FloorLocation = %s; #end\n"
"#ifndef (FloorColor) #declare FloorColor = <%1g, %1g, %1g>; #end\n"
"#ifndef (FloorAmbient) #declare FloorAmbient = %1g; #end\n"
"#ifndef (FloorDiffuse) #declare FloorDiffuse = %1g; #end\n"
"#ifndef (Floor) #declare Floor = %s; #end\n",
FloorAxis, FloorLocation, FloorColor[0], FloorColor[1], FloorColor[2], FloorAmbient, FloorDiffuse, (POVRayOptions.ExcludeFloor ? "false" : "true"));
POVFile.WriteLine(Line);
sprintf(Line,
"#ifndef (Ambient) #declare Ambient = 0.4; #end\n"
"#ifndef (Diffuse) #declare Diffuse = 0.4; #end\n"
"#ifndef (Reflection) #declare Reflection = 0.08; #end\n"
"#ifndef (Phong) #declare Phong = 0.5; #end\n"
"#ifndef (PhongSize) #declare PhongSize = 40; #end\n"
"#ifndef (TransReflection) #declare TransReflection = 0.2; #end\n"
"#ifndef (TransFilter) #declare TransFilter = 0.85; #end\n"
"#ifndef (TransIoR) #declare TransIoR = 1.25; #end\n"
"#ifndef (RubberReflection) #declare RubberReflection = 0; #end\n"
"#ifndef (RubberPhong) #declare RubberPhong = 0.1; #end\n"
"#ifndef (RubberPhongS) #declare RubberPhongS = 10; #end\n"
"#ifndef (ChromeReflection) #declare ChromeReflection = 0.85; #end\n"
"#ifndef (ChromeBrilliance) #declare ChromeBrilliance = 5; #end\n"
"#ifndef (ChromeSpecular) #declare ChromeSpecular = 0.8; #end\n"
"#ifndef (ChromeRough) #declare ChromeRough = 0.01; #end\n"
"#ifndef (OpaqueNormal) #declare OpaqueNormal = normal { bumps 0.001 scale 0.5 }; #end\n"
"#ifndef (TransNormal) #declare TransNormal = normal { bumps 0.001 scale 0.5 }; #end\n");
POVFile.WriteLine(Line);
sprintf(Line,
"#ifndef (Quality) #declare Quality = 3; #end\n"
"#ifndef (Studs) #declare Studs = 1; #end\n"
"#ifndef (LgeoLibrary) #declare LgeoLibrary = %s; #end\n"
"#ifndef (ModelReflection) #declare ModelReflection = %i; #end\n"
"#ifndef (ModelShadow) #declare ModelShadow = %i; #end\n\n",
(POVRayOptions.UseLGEO ? "true" : "false"), (POVRayOptions.NoReflection ? 0 : 1), (POVRayOptions.NoShadow ? 0 : 1));
POVFile.WriteLine(Line);
sprintf(Line,
"#ifndef (SkipWriteLightMacro)\n"
"#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, FadeDistance, FadePower, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n"
" #local PointLight = %i;\n"
" #local Spotlight = %i;\n"
" #local DirectionalLight = %i;\n"
" #local AreaLight = %i;\n"
" light_source {\n"
" Location\n"
" color rgb Color*Power\n"
" #if (Shadowless > 0)\n"
" shadowless\n"
" #end\n"
" #if (FadeDistance > 0)\n"
" fade_distance FadeDistance\n"
" #end\n"
" #if (FadePower > 0)\n"
" fade_power FadePower\n"
" #end\n"
" #if (Type = Spotlight)\n"
" spotlight\n"
" radius SpotRadius\n"
" falloff SpotFalloff\n"
" tightness SpotTightness\n"
" point_at Target\n"
" #elseif (Type = DirectionalLight)\n"
" parallel\n"
" point_at Target\n"
" #elseif (Type = AreaLight)\n"
" area_light AreaWidth, AreaHeight, AreaRows, AreaColumns\n"
" jitter\n"
" #if (AreaCircle > 0 & AreaWidth > 2 & AreaHeight > 2 & AreaRows > 1 & AreaColumns > 1 )\n"
" circular \n"
" #if (AreaWidth = AreaHeight & AreaRows = AreaColumns)\n"
" orient\n"
" #end\n"
" #end\n"
" #end\n"
" }\n"
"#end\n"
"#end\n\n",
lcLightType::Point, lcLightType::Spot, lcLightType::Directional, lcLightType::Area);
POVFile.WriteLine(Line);
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
int ColorIdx = ModelPart.ColorIndex;
if (lcIsColorTranslucent(ColorIdx))
{
if (!ColorMacros.contains("TranslucentColor"))
{
sprintf(Line,
"#ifndef (SkipTranslucentColorMacro)\n"
"#macro TranslucentColor(r, g, b, f)\n"
" material {\n"
" texture {\n"
" pigment { srgbf <r,g,b,f> }\n"
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
" finish { phong Phong phong_size PhongSize reflection TransReflection }\n"
" normal { TransNormal }\n"
" }\n"
" interior { ior TransIoR }\n"
" }\n"
"#end\n"
"#end\n\n");
POVFile.WriteLine(Line);
ColorMacros.append("TranslucentColor");
}
}
else if (lcIsColorChrome(ColorIdx))
{
if (!ColorMacros.contains("ChromeColor"))
{
sprintf(Line,
"#ifndef (SkipChromeColorMacro)\n"
"#macro ChromeColor(r, g, b)\n"
"#if (LgeoLibrary) material { #end\n"
" texture {\n"
" pigment { srgbf <r,g,b,0> }\n"
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
" finish { phong Phong phong_size PhongSize reflection ChromeReflection brilliance ChromeBrilliance metallic specular ChromeSpecular roughness ChromeRough }\n"
" }\n"
"#if (LgeoLibrary) } #end\n"
"#end\n"
"#end\n\n");
POVFile.WriteLine(Line);
ColorMacros.append("ChromeColor");
}
}
else if (lcIsColorRubber(ColorIdx))
{
if (!ColorMacros.contains("RubberColor"))
{
sprintf(Line,
"#ifndef (SkipRubberColorMacro)\n"
"#macro RubberColor(r, g, b)\n"
"#if (LgeoLibrary) material { #end\n"
" texture {\n"
" pigment { srgbf <r,g,b,0> }\n"
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
" finish { phong RubberPhong phong_size RubberPhongS reflection RubberReflection }\n"
" }\n"
"#if (LgeoLibrary) } #end\n"
"#end\n"
"#end\n\n");
POVFile.WriteLine(Line);
ColorMacros.append("RubberColor");
}
}
else
{
if (!ColorMacros.contains("OpaqueColor"))
{
sprintf(Line,
"#ifndef (SkipOpaqueColorMacro)\n"
"#macro OpaqueColor(r, g, b)\n"
"#if (LgeoLibrary) material { #end\n"
" texture {\n"
" pigment { srgbf <r,g,b,0> }\n"
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
" finish { phong Phong phong_size PhongSize reflection Reflection }\n"
" normal { OpaqueNormal }\n"
" }\n"
"#if (LgeoLibrary) } #end\n"
"#end\n"
"#end\n\n");
POVFile.WriteLine(Line);
ColorMacros.append("OpaqueColor");
}
}
}
sprintf(Line, "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n");
POVFile.WriteLine(Line);
sprintf(Line, "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n",
(CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData()));
POVFile.WriteLine(Line);
lcVector3 AreaX(1.0f, 0.0f, 0.0f), AreaY(0.0f, 1.0f, 0.0f);
lcVector2i AreaGrid(1, 1);
int AreaCircle = 0, Shadowless = 0;
lcLightType LightType = lcLightType::Area;
float Power = 0.0f, FadeDistance = 0.0f, FadePower = 0.0f, SpotRadius = 0.0f, SpotFalloff = 0.0f, SpotTightness = 0.0f;
if (Lights.IsEmpty())
{
const lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f);
lcVector3 Location[4];
Location[0] = {0.0f * Radius + Center[0], -1.5f * Radius + Center[1], -1.5f * Radius + Center[2]};
Location[1] = {1.5f * Radius + Center[0], -1.0f * Radius + Center[1], 0.866026f * Radius + Center[2]};
Location[2] = {0.0f * Radius + Center[0], -2.0f * Radius + Center[1], 0.0f * Radius + Center[2]};
Location[3] = {2.0f * Radius + Center[0], 0.0f * Radius + Center[1], -2.0f * Radius + Center[2]};
for (int Idx = 0; Idx < 4; Idx++)
{
Power = Idx < 2 ? 0.75f : 0.5f;
sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n",
Idx,
LightType,
Shadowless,
Location[Idx][0], Location[Idx][1], Location[Idx][2],
LightTarget[0], LightTarget[1], LightTarget[2],
LightColor[0], LightColor[1], LightColor[2],
Power,
FadeDistance, FadePower,
SpotRadius, SpotFalloff, SpotTightness,
AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y);
POVFile.WriteLine(Line);
}
}
else
{
for (const lcLight* Light : Lights)
{
const lcVector3 LightPosition = Light->GetPosition();
const lcVector3 LightTarget = LightPosition + Light->GetDirection();
const lcVector3 LightColor = Light->GetColor();
const QString LightName = QString(Light->GetName()).replace(" ", "_");
LightType = Light->GetLightType();
Shadowless = Light->GetCastShadow() ? 0 : 1;
Power = Light->GetPower();
FadeDistance = Light->GetAttenuationDistance();
FadePower = Light->GetAttenuationPower();
switch (LightType)
{
case lcLightType::Point:
break;
case lcLightType::Spot:
SpotFalloff = Light->GetSpotConeAngle() / 2.0f;
SpotRadius = SpotFalloff - Light->GetSpotPenumbraAngle();
break;
case lcLightType::Directional:
break;
case lcLightType::Area:
AreaCircle = (Light->GetAreaShape() == lcLightAreaShape::Disk || Light->GetAreaShape() == lcLightAreaShape::Ellipse) ? 1 : 0;
AreaX = lcVector3(Light->GetWorldMatrix()[0]) * Light->GetSize().x;
AreaY = lcVector3(Light->GetWorldMatrix()[1]) * Light->GetSize().y;
AreaGrid = Light->GetAreaGrid();
break;
case lcLightType::Count:
break;
}
sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %g, %g, %i, <%g, %g, %g>, <%g, %g, %g>, %i, %i)\n#end\n\n",
LightName.toLatin1().constData(),
LightType,
Shadowless,
LightPosition[1], LightPosition[0], LightPosition[2],
LightTarget[1], LightTarget[0], LightTarget[2],
LightColor[0], LightColor[1], LightColor[2],
Power,
FadeDistance, FadePower,
SpotRadius, SpotFalloff, SpotTightness,
AreaCircle, AreaX[0], AreaX[1], AreaX[2], AreaY[0], AreaY[1], AreaY[2], AreaGrid.x, AreaGrid.y);
POVFile.WriteLine(Line);
}
}
POVFile.WriteLine("#ifndef (lg_quality) #declare lg_quality = Quality; #end\n\n");
if (UseLGEO)
{
memset(Line, 0, 1024);
POVFile.WriteLine("#ifndef (lg_studs) #declare lg_studs = Studs; #end\n\n");
POVFile.WriteLine("#if (lg_quality = 3) #declare lg_quality = 4; #end\n\n");
POVFile.WriteLine("#include \"lg_defs.inc\"\n\n#include \"lg_color.inc\"\n\n");
lcDiskFile TableFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_elements.lst")).absoluteFilePath());
if (!TableFile.Open(QIODevice::ReadOnly))
@ -1869,6 +2253,7 @@ bool Project::ExportPOVRay(const QString& FileName)
while (TableFile.ReadLine(Line, sizeof(Line)))
{
char Src[129], Dst[129], Flags[11];
if (*Line == ';')
@ -1877,20 +2262,22 @@ bool Project::ExportPOVRay(const QString& FileName)
if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3)
continue;
strcat(Src, ".dat");
strncat(Src, ".dat", 4);
PieceInfo* Info = Library->FindPiece(Src, nullptr, false, false);
if (!Info)
continue;
if (strchr(Flags, 'L'))
bool LgeoPartFound = false;
if ((LgeoPartFound = strchr(Flags, 'L')))
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
Entry.second |= LGEO_PIECE_LGEO;
sprintf(Entry.first, "lg_%s", Dst);
}
if (strchr(Flags, 'A'))
if (strchr(Flags, 'A') && !LgeoPartFound)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
Entry.second |= LGEO_PIECE_AR;
@ -1905,15 +2292,15 @@ bool Project::ExportPOVRay(const QString& FileName)
}
}
lcDiskFile ColorFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_colors.lst")).absoluteFilePath());
lcDiskFile LgeoColorFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_colors.lst")).absoluteFilePath());
if (!ColorFile.Open(QIODevice::ReadOnly))
if (!LgeoColorFile.Open(QIODevice::ReadOnly))
{
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Could not find LGEO files in folder '%1'.").arg(LGEOPath));
return false;
}
while (ColorFile.ReadLine(Line, sizeof(Line)))
while (LgeoColorFile.ReadLine(Line, sizeof(Line)))
{
char Name[1024], Flags[1024];
int Code;
@ -1924,20 +2311,82 @@ bool Project::ExportPOVRay(const QString& FileName)
if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3)
continue;
size_t Color = lcGetColorIndex(Code);
if (Color >= NumColors)
size_t ColorIdx = lcGetColorIndex(Code);
if (ColorIdx >= NumColors)
continue;
strcpy(ColorTable[Color].data(), Name);
strncpy(LgeoColorTable[ColorIdx].data(), Name, LC_MAX_COLOR_NAME);
}
}
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
size_t ColorIdx = ModelPart.ColorIndex;
if (!ColorTable[ColorIdx][0])
{
lcColor* Color = &gColorList[ColorIdx];
if (!LgeoColorTable[ColorIdx][0])
{
sprintf(ColorTable[ColorIdx].data(), "lc_%s", Color->SafeName);
if (lcIsColorTranslucent(ColorIdx))
{
if (!UseLGEO && !MaterialColors.contains(ColorTable[ColorIdx].data()))
MaterialColors.append(ColorTable[ColorIdx].data());
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n",
Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
}
else
{
char MacroName[LC_MAX_COLOR_NAME];
if (lcIsColorChrome(ColorIdx))
sprintf(MacroName, "Chrome");
else if (lcIsColorRubber(ColorIdx))
sprintf(MacroName, "Rubber");
else
sprintf(MacroName, "Opaque");
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n",
Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]);
}
}
else
{
sprintf(ColorTable[ColorIdx].data(), "LDXColor%i", Color->Code);
sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n",
Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIdx].data());
}
POVFile.WriteLine(Line);
}
}
if (!ColorTable[lcGetColorIndex(TopModelColorCode)][0])
{
size_t ColorIdx = lcGetColorIndex(TopModelColorCode);
lcColor* Color = &gColorList[ColorIdx];
sprintf(ColorTable[ColorIdx].data(), "LDXColor%i", Color->Code);
if (!LgeoColorTable[ColorIdx][0])
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = OpaqueColor(%g, %g, %g)\n#end\n\n",
Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
else
sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n",
Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIdx].data());
POVFile.WriteLine(Line);
}
std::set<lcMesh*> AddedMeshes;
if (!LGEOPath.isEmpty())
if (UseLGEO)
{
POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n");
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
if (ModelPart.Mesh)
@ -1958,7 +2407,7 @@ bool Project::ExportPOVRay(const QString& FileName)
const std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = Search->second;
if (Entry.first[0])
{
sprintf(Line, "#include \"%s.inc\"\n", Entry.first);
sprintf(Line, "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription);
POVFile.WriteLine(Line);
}
}
@ -1966,29 +2415,6 @@ bool Project::ExportPOVRay(const QString& FileName)
POVFile.WriteLine("\n");
}
for (size_t ColorIdx = 0; ColorIdx < gColorList.size(); ColorIdx++)
{
lcColor* Color = &gColorList[ColorIdx];
if (lcIsColorTranslucent(ColorIdx))
{
sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> filter 0.9 } finish { ambient 0.3 diffuse 0.2 reflection 0.25 phong 0.3 phong_size 60 } }\n",
Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
}
else
{
sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> } finish { ambient 0.1 phong 0.2 phong_size 20 } }\n",
Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
}
POVFile.WriteLine(Line);
if (!ColorTable[ColorIdx][0])
sprintf(ColorTable[ColorIdx].data(), "lc_%s", Color->SafeName);
}
POVFile.WriteLine("\n");
std::vector<const char*> ColorTablePointer;
ColorTablePointer.resize(NumColors);
for (size_t ColorIdx = 0; ColorIdx < NumColors; ColorIdx++)
@ -1996,7 +2422,7 @@ bool Project::ExportPOVRay(const QString& FileName)
auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char (&Name)[LC_PIECE_NAME_LEN])
{
strcpy(Name, ModelPart.Info->mFileName);
strncpy(Name, ModelPart.Info->mFileName, sizeof(Name));
for (char* c = Name; *c; c++)
if (*c == '-' || *c == '.')
@ -2006,7 +2432,7 @@ bool Project::ExportPOVRay(const QString& FileName)
{
char Suffix[32];
sprintf(Suffix, "_%p", ModelPart.Mesh);
strncat(Name, Suffix, sizeof(Name) - 1);
strncat(Name, Suffix, sizeof(Name) - strlen(Name) - 1);
Name[sizeof(Name) - 1] = 0;
}
};
@ -2027,7 +2453,7 @@ bool Project::ExportPOVRay(const QString& FileName)
if (!ModelPart.Mesh)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
strcpy(Entry.first, "lc_");
strncpy(Entry.first, "lc_", 3);
strncat(Entry.first, Name, sizeof(Entry.first) - 1);
Entry.first[sizeof(Entry.first) - 1] = 0;
}
@ -2038,65 +2464,30 @@ bool Project::ExportPOVRay(const QString& FileName)
POVFile.WriteLine(Line);
}
const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera();
const lcVector3& Position = Camera->mPosition;
const lcVector3& Target = Camera->mTargetPosition;
const lcVector3& Up = Camera->mUpVector;
sprintf(Line, "camera {\n perspective\n right x * image_width / image_height\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f * image_width / image_height\n}\n\n",
Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy);
POVFile.WriteLine(Line);
lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor);
sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\n", BackgroundColor[0], BackgroundColor[1], BackgroundColor[2]);
POVFile.WriteLine(Line);
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX);
lcVector3 Max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
lcVector3 Points[8];
lcGetBoxCorners(ModelPart.Info->GetBoundingBox(), Points);
for (int PointIdx = 0; PointIdx < 8; PointIdx++)
{
lcVector3 Point = lcMul31(Points[PointIdx], ModelPart.WorldMatrix);
Min = lcMin(Point, Min);
Max = lcMax(Point, Max);
}
}
lcVector3 Center = (Min + Max) / 2.0f;
float Radius = (Max - Center).Length() / 25.0f;
Center = lcVector3(Center[1], Center[0], Center[2]) / 25.0f;
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.75\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 0.0f * Radius + Center.x, -1.5f * Radius + Center.y, -1.5f * Radius + Center.z);
POVFile.WriteLine(Line);
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.75\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 1.5f * Radius + Center.x, -1.0f * Radius + Center.y, 0.866026f * Radius + Center.z);
POVFile.WriteLine(Line);
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 0.0f * Radius + Center.x, -2.0f * Radius + Center.y, 0.0f * Radius + Center.z);
POVFile.WriteLine(Line);
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 2.0f * Radius + Center.x, 0.0f * Radius + Center.y, -2.0f * Radius + Center.z);
sprintf(Line, "#declare %s = union {\n", TopModelName.toLatin1().constData());
POVFile.WriteLine(Line);
for (const lcModelPartsEntry& ModelPart : ModelParts)
{
int Color = ModelPart.ColorIndex;
const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : "";
int ColorIdx = ModelPart.ColorIndex;
const char* Suffix = lcIsColorTranslucent(ColorIdx) ? "_clear" : "";
const float* f = ModelPart.WorldMatrix;
char Modifier[32];
if (UseLGEO || MaterialColors.contains(ColorTable[ColorIdx].data()))
sprintf(Modifier, "material");
else
sprintf(Modifier, "texture");
if (!ModelPart.Mesh)
{
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
if (Entry.second & LGEO_PIECE_SLOPE)
{
sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n"
" object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n"
" matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Entry.first, Suffix, ColorTable[Color].data(), Entry.first, ColorTable[Color].data(),
sprintf(Line,
" merge {\n object {\n %s%s\n %s { %s }\n }\n"
" object {\n %s_slope\n texture {\n %s normal { bumps 0.3 scale 0.02 }\n }\n }\n"
" matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), Entry.first, ColorTable[ColorIdx].data(),
-f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
else
@ -2104,8 +2495,8 @@ bool Project::ExportPOVRay(const QString& FileName)
if (!ModelPart.Info || !ModelPart.Info->GetMesh())
continue;
sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Entry.first, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
sprintf(Line, " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
}
@ -2114,13 +2505,29 @@ bool Project::ExportPOVRay(const QString& FileName)
char Name[LC_PIECE_NAME_LEN];
GetMeshName(ModelPart, Name);
sprintf(Line, "object {\n lc_%s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
Name, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
sprintf(Line, " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
Name, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
}
POVFile.WriteLine(Line);
}
sprintf(Line, "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n");
POVFile.WriteLine(Line);
sprintf(Line, "object {\n %s\n %s { %s }\n}\n\n",
TopModelName.toLatin1().constData(), (UseLGEO ? "material" : "texture"), ColorTable[lcGetColorIndex(TopModelColorCode)].data());
POVFile.WriteLine(Line);
sprintf(Line, "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n");
POVFile.WriteLine(Line);
if (!POVRayOptions.FooterIncludeFile.isEmpty())
{
sprintf(Line, "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData());
POVFile.WriteLine(Line);
}
return true;
}
@ -2239,7 +2646,7 @@ void Project::SaveImage()
if (Dialog.exec() != QDialog::Accepted)
return;
QString Extension = QFileInfo(Dialog.mFileName).suffix();
if (!Extension.isEmpty())

View file

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>resources/action_arealight_16.png</file>
<file>resources/action_delete_16.png</file>
<file>resources/action_insert_16.png</file>
<file>resources/action_light_16.png</file>
@ -9,6 +10,7 @@
<file>resources/action_rotate_16.png</file>
<file>resources/action_select_16.png</file>
<file>resources/action_spotlight_16.png</file>
<file>resources/action_sunlight_16.png</file>
<file>resources/action_zoom_16.png</file>
<file>resources/edit_copy_16.png</file>
<file>resources/edit_cut_16.png</file>
@ -23,6 +25,7 @@
<file>resources/file_render_open_in_blender_16.png</file>
<file>resources/file_render_povray_16.png</file>
<file>resources/file_save_16.png</file>
<file>resources/action_arealight.png</file>
<file>resources/action_camera.png</file>
<file>resources/action_color_picker.png</file>
<file>resources/action_color_picker_16.png</file>
@ -41,9 +44,11 @@
<file>resources/action_rotate_view.png</file>
<file>resources/action_select.png</file>
<file>resources/action_spotlight.png</file>
<file>resources/action_sunlight.png</file>
<file>resources/action_zoom.png</file>
<file>resources/action_zoom_extents.png</file>
<file>resources/action_zoom_region.png</file>
<file>resources/cursor_arealight.png</file>
<file>resources/cursor_camera.png</file>
<file>resources/cursor_color_picker.png</file>
<file>resources/cursor_delete.png</file>
@ -61,6 +66,7 @@
<file>resources/cursor_select_add.png</file>
<file>resources/cursor_select_remove.png</file>
<file>resources/cursor_spotlight.png</file>
<file>resources/cursor_sunlight.png</file>
<file>resources/cursor_zoom.png</file>
<file>resources/cursor_zoom_region.png</file>
<file>resources/edit_copy.png</file>

View file

@ -160,7 +160,7 @@ void lcQPropertiesTreeDelegate::paint(QPainter *painter, const QStyleOptionViewI
QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &opt));
painter->save();
painter->setPen(QPen(color));
if (!m_treeWidget || (!m_treeWidget->lastColumn(index.column()) && hasValue))
{
int right = (option.direction == Qt::LeftToRight) ? option.rect.right() : option.rect.left();
@ -222,9 +222,9 @@ lcQPropertiesTree::lcQPropertiesTree(QWidget *parent) :
m_checkedIcon = drawCheckBox(true);
m_uncheckedIcon = drawCheckBox(false);
m_delegate = new lcQPropertiesTreeDelegate(parent);
m_delegate->setTreeWidget(this);
setItemDelegate(m_delegate);
mDelegate = new lcQPropertiesTreeDelegate(parent);
mDelegate->setTreeWidget(this);
setItemDelegate(mDelegate);
SetEmpty();
@ -264,7 +264,7 @@ void lcQPropertiesTree::keyPressEvent(QKeyEvent *event)
case Qt::Key_Return:
case Qt::Key_Enter:
case Qt::Key_Space: // Trigger Edit
if (!m_delegate->editedItem())
if (!mDelegate->editedItem())
{
if (const QTreeWidgetItem *item = currentItem())
{
@ -299,8 +299,8 @@ void lcQPropertiesTree::mousePressEvent(QMouseEvent *event)
if (item)
{
if ((item != m_delegate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) &&
((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled)))
if ((item != mDelegate->editedItem()) && (event->button() == Qt::LeftButton) && (header()->logicalIndexAt(event->pos().x()) == 1) &&
((item->flags() & (Qt::ItemIsEditable | Qt::ItemIsEnabled)) == (Qt::ItemIsEditable | Qt::ItemIsEnabled)))
editItem(item, 1);
}
}
@ -423,59 +423,63 @@ protected:
bool mAllowEmpty;
};
QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item) const
QWidget* lcQPropertiesTree::createEditor(QWidget* Parent, QTreeWidgetItem* Item) const
{
PropertyType propertyType = (PropertyType)item->data(0, lcQPropertiesTree::PropertyTypeRole).toInt();
lcQPropertiesTree::PropertyType PropertyType = (lcQPropertiesTree::PropertyType)Item->data(0, lcQPropertiesTree::PropertyTypeRole).toInt();
switch (propertyType)
switch (PropertyType)
{
case PropertyGroup:
return nullptr;
case PropertyBool:
{
QCheckBox *editor = new QCheckBox(parent);
bool value = item->data(0, PropertyValueRole).toBool();
editor->setChecked(value);
connect(editor, SIGNAL(toggled(bool)), this, SLOT(slotToggled(bool)));
return editor;
}
return nullptr;
case PropertyFloat:
{
QLineEdit *editor = new QLineEdit(parent);
float value = item->data(0, PropertyValueRole).toFloat();
QLineEdit* Editor = new QLineEdit(Parent);
float Value = Item->data(0, PropertyValueRole).toFloat();
QPointF Range = Item->data(0, PropertyRangeRole).toPointF();
editor->setValidator(new QDoubleValidator(editor));
editor->setText(lcFormatValueLocalized(value));
Editor->setValidator(Range.isNull() ? new QDoubleValidator(Editor) : new QDoubleValidator(Range.x(), Range.y(), 1, Editor));
Editor->setText(lcFormatValueLocalized(Value));
connect(editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
connect(Editor, &QLineEdit::returnPressed, this, &lcQPropertiesTree::slotReturnPressed);
return editor;
return Editor;
}
case PropertyInteger:
{
QLineEdit* Editor = new QLineEdit(Parent);
int Value = Item->data(0, PropertyValueRole).toInt();
QPoint Range = Item->data(0, PropertyRangeRole).toPoint();
Editor->setValidator(Range.isNull() ? new QIntValidator(Editor) : new QIntValidator(Range.x(), Range.y(), Editor));
Editor->setText(QString::number(Value));
connect(Editor, &QLineEdit::returnPressed, this, &lcQPropertiesTree::slotReturnPressed);
return Editor;
}
case PropertyStep:
{
QLineEdit* Editor = new QLineEdit(parent);
QLineEdit* Editor = new QLineEdit(Parent);
lcStep Value = item->data(0, PropertyValueRole).toUInt();
lcStep Value = Item->data(0, PropertyValueRole).toUInt();
lcStep Show = partShow->data(0, PropertyValueRole).toUInt();
lcStep Hide = partHide->data(0, PropertyValueRole).toUInt();
if (Show && Hide)
{
if (item == partShow)
if (Item == partShow)
Editor->setValidator(new lcStepValidator(1, Hide - 1, false));
else
Editor->setValidator(new lcStepValidator(Show + 1, LC_STEP_MAX, true));
}
else
Editor->setValidator(new lcStepValidator(1, LC_STEP_MAX, item == partHide));
Editor->setValidator(new lcStepValidator(1, LC_STEP_MAX, Item == partHide));
if (item != partHide || Value != LC_STEP_MAX)
if (Item != partHide || Value != LC_STEP_MAX)
Editor->setText(QString::number(Value));
connect(Editor, SIGNAL(returnPressed()), this, SLOT(slotReturnPressed()));
@ -485,8 +489,8 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item)
case PropertyString:
{
QLineEdit *editor = new QLineEdit(parent);
QString value = item->data(0, PropertyValueRole).toString();
QLineEdit *editor = new QLineEdit(Parent);
QString value = Item->data(0, PropertyValueRole).toString();
editor->setText(value);
@ -495,10 +499,49 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item)
return editor;
}
case PropertyStringList:
{
QComboBox* editor = new QComboBox(Parent);
if (Item == mCameraProjectionItem)
{
editor->addItems( { tr("Perspective"), tr("Orthographic") } );
}
else if (Item == mLightTypeItem)
{
for (int LightTypeIndex = 0; LightTypeIndex < static_cast<int>(lcLightType::Count); LightTypeIndex++)
editor->addItem(lcLight::GetLightTypeString(static_cast<lcLightType>(LightTypeIndex)));
}
else if (Item == mLightAreaShapeItem)
{
for (int LightAreaShapeIndex = 0; LightAreaShapeIndex < static_cast<int>(lcLightAreaShape::Count); LightAreaShapeIndex++)
editor->addItem(lcLight::GetAreaShapeString(static_cast<lcLightAreaShape>(LightAreaShapeIndex)));
}
int value = Item->data(0, PropertyValueRole).toInt();
editor->setCurrentIndex(value);
connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int)));
return editor;
}
case PropertyColor:
{
QPushButton *editor = new QPushButton(parent);
int value = item->data(0, PropertyValueRole).toInt();
QPushButton *Editor = new QPushButton(Parent);
QColor Value = Item->data(0, PropertyValueRole).value<QColor>();
UpdateLightColorEditor(Editor, Value);
connect(Editor, &QPushButton::clicked, this, &lcQPropertiesTree::LightColorButtonClicked);
return Editor;
}
case PropertyPieceColor:
{
QPushButton *editor = new QPushButton(Parent);
int value = Item->data(0, PropertyValueRole).toInt();
updateColorEditor(editor, value);
@ -509,7 +552,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item)
case PropertyPart:
{
QComboBox *editor = new QComboBox(parent);
QComboBox *editor = new QComboBox(Parent);
editor->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
editor->setMinimumContentsLength(1);
@ -537,7 +580,7 @@ QWidget *lcQPropertiesTree::createEditor(QWidget *parent, QTreeWidgetItem *item)
for (PieceInfo* Info : SortedPieces)
editor->addItem(Info->m_strDescription, QVariant::fromValue((void*)Info));
PieceInfo *info = (PieceInfo*)item->data(0, PropertyValueRole).value<void*>();
PieceInfo *info = (PieceInfo*)Item->data(0, PropertyValueRole).value<void*>();
editor->setCurrentIndex(editor->findData(QVariant::fromValue((void*)info)));
connect(editor, SIGNAL(currentIndexChanged(int)), this, SLOT(slotSetValue(int)));
@ -567,22 +610,38 @@ void lcQPropertiesTree::updateColorEditor(QPushButton *editor, int value) const
editor->setText(color->Name);
}
void lcQPropertiesTree::UpdateLightColorEditor(QPushButton* Editor, QColor Color) const
{
QImage Image(12, 12, QImage::Format_ARGB32);
Image.fill(0);
QPainter Painter(&Image);
Painter.setCompositionMode(QPainter::CompositionMode_Source);
Painter.setPen(Qt::darkGray);
Painter.setBrush(Color);
Painter.drawRect(0, 0, Image.width() - 1, Image.height() - 1);
Painter.end();
Editor->setStyleSheet("Text-align:left");
Editor->setIcon(QPixmap::fromImage(Image));
Editor->setText(Color.name().toUpper());
}
void lcQPropertiesTree::slotToggled(bool Value)
{
QTreeWidgetItem* Item = m_delegate->editedItem();
QTreeWidgetItem* Item = mDelegate->editedItem();
lcModel* Model = gMainWindow->GetActiveModel();
lcObject* Focus = Model->GetFocusObject();
if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA)
if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT)
{
lcObject* Focus = Model->GetFocusObject();
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
if (Focus && Focus->IsCamera())
if (Light)
{
lcCamera* Camera = (lcCamera*)Focus;
if (Item == cameraOrtho)
if (Item == mLightCastShadowItem)
{
Model->SetCameraOrthographic(Camera, Value);
Model->SetLightCastShadow(Light, Value);
}
}
}
@ -591,53 +650,57 @@ void lcQPropertiesTree::slotToggled(bool Value)
void lcQPropertiesTree::slotReturnPressed()
{
QLineEdit* Editor = (QLineEdit*)sender();
QTreeWidgetItem* Item = m_delegate->editedItem();
QTreeWidgetItem* Item = mDelegate->editedItem();
lcModel* Model = gMainWindow->GetActiveModel();
lcPiece* Piece = (mFocus && mFocus->IsPiece()) ? (lcPiece*)mFocus : nullptr;
lcLight* Light = (mFocus && mFocus->IsLight()) ? (lcLight*)mFocus : nullptr;
if (Item == mPositionXItem || Item == mPositionYItem || Item == mPositionZItem)
{
lcVector3 Center;
lcMatrix33 RelativeRotation;
Model->GetMoveRotateTransform(Center, RelativeRotation);
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
if (Item == mPositionXItem)
Position[0] = Value;
else if (Item == mPositionYItem)
Position[1] = Value;
else if (Item == mPositionZItem)
Position[2] = Value;
lcVector3 Distance = Position - Center;
Model->MoveSelectedObjects(Distance, Distance, false, true, true, true);
}
else if (Item == mRotationXItem || Item == mRotationYItem || Item == mRotationZItem)
{
lcVector3 InitialRotation(0.0f, 0.0f, 0.0f);
if (Piece)
InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD;
else if (Light)
InitialRotation = lcMatrix44ToEulerAngles(Light->mWorldMatrix) * LC_RTOD;
lcVector3 Rotation = InitialRotation;
float Value = lcParseValueLocalized(Editor->text());
if (Item == mRotationXItem)
Rotation[0] = Value;
else if (Item == mRotationYItem)
Rotation[1] = Value;
else if (Item == mRotationZItem)
Rotation[2] = Value;
Model->RotateSelectedObjects(Rotation - InitialRotation, true, false, true, true);
}
if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE)
{
lcPiece* Piece = (mFocus && mFocus->IsPiece()) ? (lcPiece*)mFocus : nullptr;
if (Item == partPositionX || Item == partPositionY || Item == partPositionZ)
{
lcVector3 Center;
lcMatrix33 RelativeRotation;
Model->GetMoveRotateTransform(Center, RelativeRotation);
lcVector3 Position = Center;
float Value = lcParseValueLocalized(Editor->text());
if (Item == partPositionX)
Position[0] = Value;
else if (Item == partPositionY)
Position[1] = Value;
else if (Item == partPositionZ)
Position[2] = Value;
lcVector3 Distance = Position - Center;
Model->MoveSelectedObjects(Distance, Distance, false, false, true, true);
}
else if (Item == partRotationX || Item == partRotationY || Item == partRotationZ)
{
lcVector3 InitialRotation;
if (Piece)
InitialRotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD;
else
InitialRotation = lcVector3(0.0f, 0.0f, 0.0f);
lcVector3 Rotation = InitialRotation;
float Value = lcParseValueLocalized(Editor->text());
if (Item == partRotationX)
Rotation[0] = Value;
else if (Item == partRotationY)
Rotation[1] = Value;
else if (Item == partRotationZ)
Rotation[2] = Value;
Model->RotateSelectedPieces(Rotation - InitialRotation, true, false, true, true);
}
else if (Item == partShow)
if (Item == partShow)
{
bool Ok = false;
lcStep Step = Editor->text().toUInt(&Ok);
@ -736,7 +799,7 @@ void lcQPropertiesTree::slotReturnPressed()
Model->SetCameraZFar(Camera, Value);
}
else if (Item == cameraName)
else if (Item == mCameraNameItem)
{
QString Value = Editor->text();
@ -744,23 +807,99 @@ void lcQPropertiesTree::slotReturnPressed()
}
}
}
else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT)
{
if (Light)
{
if (Item == mLightAttenuationDistanceItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetLightAttenuationDistance(Light, Value);
}
else if (Item == mLightAttenuationPowerItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetLightAttenuationPower(Light, Value);
}
else if (Item == mLightSpotConeAngleItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetSpotLightConeAngle(Light, Value);
}
else if (Item == mLightSpotPenumbraAngleItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetSpotLightPenumbraAngle(Light, Value);
}
else if (Item == mLightSpotTightnessItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetSpotLightTightness(Light, Value);
}
else if (Item == mLightAreaGridXItem)
{
lcVector2i AreaGrid = Light->GetAreaGrid();
AreaGrid.x = Editor->text().toInt();
Model->SetLightAreaGrid(Light, AreaGrid);
}
else if (Item == mLightAreaGridYItem)
{
lcVector2i AreaGrid = Light->GetAreaGrid();
AreaGrid.y = Editor->text().toInt();
Model->SetLightAreaGrid(Light, AreaGrid);
}
else if (Item == mLightSizeXItem)
{
lcVector2 Value = Light->GetSize();
Value[0] = lcParseValueLocalized(Editor->text());
Model->SetLightSize(Light, Value);
}
else if (Item == mLightSizeYItem)
{
lcVector2 Value = Light->GetSize();
Value[1] = lcParseValueLocalized(Editor->text());
Model->SetLightSize(Light, Value);
}
else if (Item == mLightPowerItem)
{
float Value = lcParseValueLocalized(Editor->text());
Model->SetLightPower(Light, Value);
}
else if (Item == mLightNameItem)
{
QString Value = Editor->text();
Model->SetLightName(Light, Value);
}
}
}
}
void lcQPropertiesTree::slotSetValue(int Value)
{
QTreeWidgetItem* Item = m_delegate->editedItem();
QTreeWidgetItem* Item = mDelegate->editedItem();
lcModel* Model = gMainWindow->GetActiveModel();
if (mWidgetMode == LC_PROPERTY_WIDGET_PIECE)
{
if (Item == partColor)
if (Item == mPieceColorItem)
{
Model->SetSelectedPiecesColorIndex(Value);
QPushButton *editor = (QPushButton*)m_delegate->editor();
QPushButton *editor = (QPushButton*)mDelegate->editor();
updateColorEditor(editor, Value);
}
else if (Item == partID)
else if (Item == mPieceIdItem)
{
QComboBox *editor = (QComboBox*)sender();
@ -775,6 +914,37 @@ void lcQPropertiesTree::slotSetValue(int Value)
gMainWindow->PreviewPiece(Info->mFileName, ColorCode, false);
}
}
else if (mWidgetMode == LC_PROPERTY_WIDGET_CAMERA)
{
lcObject* Focus = Model->GetFocusObject();
if (Focus && Focus->IsCamera())
{
lcCamera* Camera = (lcCamera*)Focus;
if (Item == mCameraProjectionItem)
{
Model->SetCameraOrthographic(Camera, Value == 1);
}
}
}
else if (mWidgetMode == LC_PROPERTY_WIDGET_LIGHT)
{
lcObject* Focus = Model->GetFocusObject();
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
if (Light)
{
if (Item == mLightTypeItem)
{
Model->SetLightType(Light, static_cast<lcLightType>(Value));
}
else if (Item == mLightAreaShapeItem)
{
Model->SetLightAreaShape(Light, static_cast<lcLightAreaShape>(Value));
}
}
}
}
void lcQPropertiesTree::slotColorButtonClicked()
@ -822,6 +992,28 @@ void lcQPropertiesTree::slotColorButtonClicked()
Popup->show();
}
void lcQPropertiesTree::LightColorButtonClicked()
{
lcModel* Model = gMainWindow->GetActiveModel();
lcObject* Focus = Model->GetFocusObject();
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
if (!Light)
return;
QColor Color = QColorDialog::getColor(lcQColorFromVector3(Light->GetColor()), this, tr("Select Light Color"));
if (!Color.isValid())
return;
Model->SetLightColor(Light, lcVector3FromQColor(Color));
QPushButton* Editor = qobject_cast<QPushButton*>(mDelegate->editor());
if (Editor)
UpdateLightColorEditor(Editor, Color);
}
QTreeWidgetItem *lcQPropertiesTree::addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType)
{
QTreeWidgetItem *newItem;
@ -848,20 +1040,13 @@ void lcQPropertiesTree::SetEmpty()
{
clear();
partPosition = nullptr;
partPositionX = nullptr;
partPositionY = nullptr;
partPositionZ = nullptr;
partRotation = nullptr;
partRotationX = nullptr;
partRotationY = nullptr;
partRotationZ = nullptr;
mPieceAttributesItem = nullptr;
partVisibility = nullptr;
partShow = nullptr;
partHide = nullptr;
partAppearance = nullptr;
partColor = nullptr;
partID = nullptr;
mPieceColorItem = nullptr;
mPieceIdItem = nullptr;
cameraPosition = nullptr;
cameraPositionX = nullptr;
@ -875,12 +1060,38 @@ void lcQPropertiesTree::SetEmpty()
cameraUpX = nullptr;
cameraUpY = nullptr;
cameraUpZ = nullptr;
cameraSettings = nullptr;
cameraOrtho = nullptr;
mCameraAttributesItem = nullptr;
mCameraProjectionItem = nullptr;
cameraFOV = nullptr;
cameraNear = nullptr;
cameraFar = nullptr;
cameraName = nullptr;
mCameraNameItem = nullptr;
mLightColorItem = nullptr;
mLightPowerItem = nullptr;
mLightAttributesItem = nullptr;
mLightTypeItem = nullptr;
mLightNameItem = nullptr;
mLightAttenuationDistanceItem = nullptr;
mLightAttenuationPowerItem = nullptr;
mLightSpotConeAngleItem = nullptr;
mLightSpotPenumbraAngleItem = nullptr;
mLightSpotTightnessItem = nullptr;
mLightAreaShapeItem = nullptr;
mLightAreaGridXItem = nullptr;
mLightAreaGridYItem = nullptr;
mLightSizeXItem = nullptr;
mLightSizeYItem = nullptr;
mLightCastShadowItem = nullptr;
mPositionItem = nullptr;
mPositionXItem = nullptr;
mPositionYItem = nullptr;
mPositionZItem = nullptr;
mRotationItem = nullptr;
mRotationXItem = nullptr;
mRotationYItem = nullptr;
mRotationZItem = nullptr;
mWidgetMode = LC_PROPERTY_WIDGET_EMPTY;
mFocus = nullptr;
@ -892,23 +1103,23 @@ void lcQPropertiesTree::SetPiece(const lcArray<lcObject*>& Selection, lcObject*
{
SetEmpty();
partPosition = addProperty(nullptr, tr("Position"), PropertyGroup);
partPositionX = addProperty(partPosition, tr("X"), PropertyFloat);
partPositionY = addProperty(partPosition, tr("Y"), PropertyFloat);
partPositionZ = addProperty(partPosition, tr("Z"), PropertyFloat);
partRotation = addProperty(nullptr, tr("Rotation"), PropertyGroup);
partRotationX = addProperty(partRotation, tr("X"), PropertyFloat);
partRotationY = addProperty(partRotation, tr("Y"), PropertyFloat);
partRotationZ = addProperty(partRotation, tr("Z"), PropertyFloat);
mPieceAttributesItem = addProperty(nullptr, tr("Piece Attributes"), PropertyGroup);
mPieceIdItem = addProperty(mPieceAttributesItem, tr("Part"), PropertyPart);
mPieceColorItem = addProperty(mPieceAttributesItem, tr("Color"), PropertyPieceColor);
partVisibility = addProperty(nullptr, tr("Visible Steps"), PropertyGroup);
partShow = addProperty(partVisibility, tr("Show"), PropertyStep);
partHide = addProperty(partVisibility, tr("Hide"), PropertyStep);
partAppearance = addProperty(nullptr, tr("Appearance"), PropertyGroup);
partColor = addProperty(partAppearance, tr("Color"), PropertyColor);
partID = addProperty(partAppearance, tr("Part"), PropertyPart);
mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup);
mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat);
mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat);
mPositionZItem = addProperty(mPositionItem, tr("Z"), PropertyFloat);
mRotationItem = addProperty(nullptr, tr("Rotation"), PropertyGroup);
mRotationXItem = addProperty(mRotationItem, tr("X"), PropertyFloat);
mRotationYItem = addProperty(mRotationItem, tr("Y"), PropertyFloat);
mRotationZItem = addProperty(mRotationItem, tr("Z"), PropertyFloat);
mWidgetMode = LC_PROPERTY_WIDGET_PIECE;
}
@ -919,25 +1130,29 @@ void lcQPropertiesTree::SetPiece(const lcArray<lcObject*>& Selection, lcObject*
lcVector3 Position;
lcMatrix33 RelativeRotation;
Model->GetMoveRotateTransform(Position, RelativeRotation);
partPositionX->setText(1, lcFormatValueLocalized(Position[0]));
partPositionX->setData(0, PropertyValueRole, Position[0]);
partPositionY->setText(1, lcFormatValueLocalized(Position[1]));
partPositionY->setData(0, PropertyValueRole, Position[1]);
partPositionZ->setText(1, lcFormatValueLocalized(Position[2]));
partPositionZ->setData(0, PropertyValueRole, Position[2]);
mPositionXItem->setText(1, lcFormatValueLocalized(Position[0]));
mPositionXItem->setData(0, PropertyValueRole, Position[0]);
mPositionYItem->setText(1, lcFormatValueLocalized(Position[1]));
mPositionYItem->setData(0, PropertyValueRole, Position[1]);
mPositionZItem->setText(1, lcFormatValueLocalized(Position[2]));
mPositionZItem->setData(0, PropertyValueRole, Position[2]);
lcVector3 Rotation;
if (Piece)
Rotation = lcMatrix44ToEulerAngles(Piece->mModelWorld) * LC_RTOD;
else
Rotation = lcVector3(0.0f, 0.0f, 0.0f);
partRotationX->setText(1, lcFormatValueLocalized(Rotation[0]));
partRotationX->setData(0, PropertyValueRole, Rotation[0]);
partRotationY->setText(1, lcFormatValueLocalized(Rotation[1]));
partRotationY->setData(0, PropertyValueRole, Rotation[1]);
partRotationZ->setText(1, lcFormatValueLocalized(Rotation[2]));
partRotationZ->setData(0, PropertyValueRole, Rotation[2]);
mRotationXItem->setText(1, lcFormatValueLocalized(Rotation[0]));
mRotationXItem->setData(0, PropertyValueRole, Rotation[0]);
mRotationYItem->setText(1, lcFormatValueLocalized(Rotation[1]));
mRotationYItem->setData(0, PropertyValueRole, Rotation[1]);
mRotationZItem->setText(1, lcFormatValueLocalized(Rotation[2]));
mRotationZItem->setData(0, PropertyValueRole, Rotation[2]);
lcStep Show = 0;
lcStep Hide = 0;
@ -1008,14 +1223,14 @@ void lcQPropertiesTree::SetPiece(const lcArray<lcObject*>& Selection, lcObject*
painter.drawRect(0, 0, img.width() - 1, img.height() - 1);
painter.end();
partColor->setIcon(1, QIcon(QPixmap::fromImage(img)));
partColor->setText(1, color->Name);
partColor->setData(0, PropertyValueRole, ColorIndex);
mPieceColorItem->setIcon(1, QIcon(QPixmap::fromImage(img)));
mPieceColorItem->setText(1, color->Name);
mPieceColorItem->setData(0, PropertyValueRole, ColorIndex);
QString text = Info ? Info->m_strDescription : QString();
partID->setText(1, text);
partID->setToolTip(1, text);
partID->setData(0, PropertyValueRole, QVariant::fromValue((void*)Info));
mPieceIdItem->setText(1, text);
mPieceIdItem->setToolTip(1, text);
mPieceIdItem->setData(0, PropertyValueRole, QVariant::fromValue((void*)Info));
}
void lcQPropertiesTree::SetCamera(lcObject* Focus)
@ -1024,6 +1239,13 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus)
{
SetEmpty();
mCameraAttributesItem = addProperty(nullptr, tr("Camera Attributes"), PropertyGroup);
mCameraNameItem = addProperty(mCameraAttributesItem, tr("Name"), PropertyString);
mCameraProjectionItem = addProperty(mCameraAttributesItem, tr("Projection"), PropertyStringList);
cameraFOV = addProperty(mCameraAttributesItem, tr("FOV"), PropertyFloat);
cameraNear = addProperty(mCameraAttributesItem, tr("Near"), PropertyFloat);
cameraFar = addProperty(mCameraAttributesItem, tr("Far"), PropertyFloat);
cameraPosition = addProperty(nullptr, tr("Position"), PropertyGroup);
cameraPositionX = addProperty(cameraPosition, tr("X"), PropertyFloat);
cameraPositionY = addProperty(cameraPosition, tr("Y"), PropertyFloat);
@ -1039,13 +1261,6 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus)
cameraUpY = addProperty(cameraUp, tr("Y"), PropertyFloat);
cameraUpZ = addProperty(cameraUp, tr("Z"), PropertyFloat);
cameraSettings = addProperty(nullptr, tr("Up"), PropertyGroup);
cameraOrtho = addProperty(cameraSettings, tr("Orthographic"), PropertyBool);
cameraFOV = addProperty(cameraSettings, tr("FOV"), PropertyFloat);
cameraNear = addProperty(cameraSettings, tr("Near"), PropertyFloat);
cameraFar = addProperty(cameraSettings, tr("Far"), PropertyFloat);
cameraName = addProperty(cameraSettings, tr("Name"), PropertyString);
mWidgetMode = LC_PROPERTY_WIDGET_CAMERA;
}
@ -1095,8 +1310,8 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus)
cameraUpZ->setText(1, lcFormatValueLocalized(UpVector[2]));
cameraUpZ->setData(0, PropertyValueRole, UpVector[2]);
cameraOrtho->setText(1, Ortho ? "True" : "False");
cameraOrtho->setData(0, PropertyValueRole, Ortho);
mCameraProjectionItem->setText(1, Ortho ? tr("Orthographic") : tr("Perspective"));
mCameraProjectionItem->setData(0, PropertyValueRole, Ortho);
cameraFOV->setText(1, lcFormatValueLocalized(FoV));
cameraFOV->setData(0, PropertyValueRole, FoV);
cameraNear->setText(1, lcFormatValueLocalized(ZNear));
@ -1104,18 +1319,259 @@ void lcQPropertiesTree::SetCamera(lcObject* Focus)
cameraFar->setText(1, lcFormatValueLocalized(ZFar));
cameraFar->setData(0, PropertyValueRole, ZFar);
cameraName->setText(1, Name);
cameraName->setData(0, PropertyValueRole, Name);
mCameraNameItem->setText(1, Name);
mCameraNameItem->setData(0, PropertyValueRole, Name);
}
void lcQPropertiesTree::SetLight(lcObject* Focus)
{
Q_UNUSED(Focus);
lcLight* Light = (Focus && Focus->IsLight()) ? (lcLight*)Focus : nullptr;
SetEmpty();
mFocus = nullptr;
QString Name = tr("Light");
lcLightType LightType = lcLightType::Point;
lcLightAreaShape LightAreaShape = lcLightAreaShape::Rectangle;
lcVector2 LightSize(0.0f, 0.0f);
lcVector2i AreaGrid(2, 2);
float Power = 0.0f;
float AttenuationDistance = 0.0f;
float AttenuationPower = 0.0f;
bool CastShadow = true;
lcVector3 Position(0.0f, 0.0f, 0.0f);
QColor Color(Qt::white);
float SpotConeAngle = 0.0f, SpotPenumbraAngle = 0.0f, SpotTightness = 0.0f;
// todo: light properties
if (Light)
{
Name = Light->GetName();
CastShadow = Light->GetCastShadow();
Position = Light->GetPosition();
Color = lcQColorFromVector3(Light->GetColor());
Power = Light->GetPower();
AttenuationDistance = Light->GetAttenuationDistance();
AttenuationPower = Light->GetAttenuationPower();
SpotConeAngle = Light->GetSpotConeAngle();
SpotPenumbraAngle = Light->GetSpotPenumbraAngle();
SpotTightness = Light->GetSpotTightness();
LightType = Light->GetLightType();
LightAreaShape = Light->GetAreaShape();
LightSize = Light->GetSize();
AreaGrid = Light->GetAreaGrid();
}
if (mWidgetMode != LC_PROPERTY_WIDGET_LIGHT || mLightType != LightType)
{
SetEmpty();
// Attributes
mLightAttributesItem = addProperty(nullptr, tr("Light Attributes"), PropertyGroup);
mLightNameItem = addProperty(mLightAttributesItem, tr("Name"), PropertyString);
mLightTypeItem = addProperty(mLightAttributesItem, tr("Type"), PropertyStringList);
mLightColorItem = addProperty(mLightAttributesItem, tr("Color"), PropertyColor);
mLightColorItem->setToolTip(1, tr("Color of the emitted light."));
mLightPowerItem = addProperty(mLightAttributesItem, tr("Power"), PropertyFloat);
mLightPowerItem->setToolTip(1, tr("Power of the light (Watts in Blender)."));
mLightCastShadowItem = addProperty(mLightAttributesItem, tr("Cast Shadows"), PropertyBool);
mLightAttenuationDistanceItem = addProperty(mLightAttributesItem, tr("Attenuation Distance"), PropertyFloat);
mLightAttenuationDistanceItem->setToolTip(1, tr("The distance at which the full light intensity arrives (POV-Ray only)."));
mLightAttenuationPowerItem = addProperty(mLightAttributesItem, tr("Attenuation Power"), PropertyFloat);
mLightAttenuationPowerItem->setToolTip(1, tr("Light falloff rate (POV-Ray only)."));
switch (LightType)
{
case lcLightType::Point:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Radius"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("Shadow soft size (Blender only)."));
break;
case lcLightType::Spot:
mLightSpotConeAngleItem = addProperty(mLightAttributesItem, tr("Spot Cone Angle"), PropertyFloat);
mLightSpotConeAngleItem->setToolTip(1, tr("The angle (in degrees) of the spot light's beam."));
mLightSpotPenumbraAngleItem = addProperty(mLightAttributesItem, tr("Spot Penumbra Angle"), PropertyFloat);
mLightSpotPenumbraAngleItem->setToolTip(1, tr("The angle (in degrees) over which the intensity of the spot light falls off to zero."));
mLightSpotTightnessItem = addProperty(mLightAttributesItem, tr("Spot Tightness"), PropertyFloat);
mLightSpotTightnessItem->setToolTip(1, tr("Additional exponential spot light edge softening (POV-Ray only)."));
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Radius"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("Shadow soft size (Blender only)."));
break;
case lcLightType::Directional:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Angle"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("Angular diameter of the light (Blender only)."));
break;
case lcLightType::Area:
mLightAreaShapeItem = addProperty(mLightAttributesItem, tr("Area Shape"), PropertyStringList);
mLightAreaShapeItem->setToolTip(1, tr("The shape of the area light."));
switch (LightAreaShape)
{
case lcLightAreaShape::Rectangle:
case lcLightAreaShape::Ellipse:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Area Width"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("The width (X direction) of the area light."));
mLightSizeYItem = addProperty(mLightAttributesItem, tr("Area Height"), PropertyFloat);
mLightSizeYItem->setToolTip(1, tr("The height (Y direction) of the area light."));
break;
case lcLightAreaShape::Square:
case lcLightAreaShape::Disk:
mLightSizeXItem = addProperty(mLightAttributesItem, tr("Area Size"), PropertyFloat);
mLightSizeXItem->setToolTip(1, tr("The size of the area light."));
mLightSizeYItem = nullptr;
break;
case lcLightAreaShape::Count:
break;
}
mLightAreaGridXItem = addProperty(mLightAttributesItem, tr("Area Grid X"), PropertyInteger);
mLightAreaGridXItem->setToolTip(1, tr("Number of point sources along the X axis (POV-Ray only)."));
mLightAreaGridXItem->setData(0, PropertyRangeRole, QPointF(1, INT_MAX));
mLightAreaGridYItem = addProperty(mLightAttributesItem, tr("Area Grid Y"), PropertyInteger);
mLightAreaGridYItem->setToolTip(1, tr("Number of point sources along the Y axis (POV-Ray only)."));
mLightAreaGridYItem->setData(0, PropertyRangeRole, QPointF(1, INT_MAX));
break;
case lcLightType::Count:
break;
}
mPositionItem = addProperty(nullptr, tr("Position"), PropertyGroup);
mPositionXItem = addProperty(mPositionItem, tr("X"), PropertyFloat);
mPositionYItem = addProperty(mPositionItem, tr("Y"), PropertyFloat);
mPositionZItem = addProperty(mPositionItem, tr("Z"), PropertyFloat);
if (LightType != lcLightType::Point)
{
mRotationItem = addProperty(nullptr, tr("Rotation"), PropertyGroup);
mRotationXItem = addProperty(mRotationItem, tr("X"), PropertyFloat);
mRotationYItem = addProperty(mRotationItem, tr("Y"), PropertyFloat);
mRotationZItem = addProperty(mRotationItem, tr("Z"), PropertyFloat);
}
mWidgetMode = LC_PROPERTY_WIDGET_LIGHT;
mLightType = LightType;
}
mFocus = Light;
mPositionXItem->setText(1, lcFormatValueLocalized(Position[0]));
mPositionXItem->setData(0, PropertyValueRole, Position[0]);
mPositionYItem->setText(1, lcFormatValueLocalized(Position[1]));
mPositionYItem->setData(0, PropertyValueRole, Position[1]);
mPositionZItem->setText(1, lcFormatValueLocalized(Position[2]));
mPositionZItem->setData(0, PropertyValueRole, Position[2]);
if (LightType != lcLightType::Point)
{
lcVector3 Rotation;
if (Light)
Rotation = lcMatrix44ToEulerAngles(Light->mWorldMatrix) * LC_RTOD;
else
Rotation = lcVector3(0.0f, 0.0f, 0.0f);
mRotationXItem->setText(1, lcFormatValueLocalized(Rotation[0]));
mRotationXItem->setData(0, PropertyValueRole, Rotation[0]);
mRotationYItem->setText(1, lcFormatValueLocalized(Rotation[1]));
mRotationYItem->setData(0, PropertyValueRole, Rotation[1]);
mRotationZItem->setText(1, lcFormatValueLocalized(Rotation[2]));
mRotationZItem->setData(0, PropertyValueRole, Rotation[2]);
}
QImage ColorImage(16, 16, QImage::Format_ARGB32);
ColorImage.fill(0);
QPainter painter(&ColorImage);
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.setPen(Qt::darkGray);
painter.setBrush(Color);
painter.drawRect(0, 0, ColorImage.width() - 1, ColorImage.height() - 1);
painter.end();
mLightColorItem->setIcon(1, QIcon(QPixmap::fromImage(ColorImage)));
mLightColorItem->setText(1, Color.name().toUpper());
mLightColorItem->setData(0, PropertyValueRole, Color);
mLightPowerItem->setText(1, lcFormatValueLocalized(Power));
mLightPowerItem->setData(0, PropertyValueRole, Power);
mLightAttenuationDistanceItem->setText(1, lcFormatValueLocalized(AttenuationDistance));
mLightAttenuationDistanceItem->setData(0, PropertyValueRole, AttenuationDistance);
mLightAttenuationDistanceItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX));
mLightAttenuationPowerItem->setText(1, lcFormatValueLocalized(AttenuationPower));
mLightAttenuationPowerItem->setData(0, PropertyValueRole, AttenuationPower);
mLightAttenuationPowerItem->setData(0, PropertyRangeRole, QPointF(0.0, FLT_MAX));
mLightTypeItem->setText(1, lcLight::GetLightTypeString(LightType));
mLightTypeItem->setData(0, PropertyValueRole, static_cast<int>(LightType));
mLightCastShadowItem->setCheckState(1, CastShadow ? Qt::Checked : Qt::Unchecked);
mLightCastShadowItem->setData(0, PropertyValueRole, CastShadow);
mLightSizeXItem->setText(1, lcFormatValueLocalized(LightSize[0]));
mLightSizeXItem->setData(0, PropertyValueRole, LightSize[0]);
if (mLightSizeYItem)
{
mLightSizeYItem->setText(1, lcFormatValueLocalized(LightSize[1]));
mLightSizeYItem->setData(0, PropertyValueRole, LightSize[1]);
}
switch (LightType)
{
case lcLightType::Point:
break;
case lcLightType::Spot:
mLightSpotConeAngleItem->setText(1, lcFormatValueLocalized(SpotConeAngle));
mLightSpotConeAngleItem->setData(0, PropertyValueRole, SpotConeAngle);
mLightSpotConeAngleItem->setData(0, PropertyRangeRole, QPointF(1.0, 180.0));
mLightSpotPenumbraAngleItem->setText(1, lcFormatValueLocalized(SpotPenumbraAngle));
mLightSpotPenumbraAngleItem->setData(0, PropertyValueRole, SpotPenumbraAngle);
mLightSpotPenumbraAngleItem->setData(0, PropertyRangeRole, QPointF(0.0, 180.0));
mLightSpotTightnessItem->setText(1, lcFormatValueLocalized(SpotTightness));
mLightSpotTightnessItem->setData(0, PropertyValueRole, SpotTightness);
mLightSpotTightnessItem->setData(0, PropertyRangeRole, QPointF(0.0, 100.0));
break;
case lcLightType::Directional:
break;
case lcLightType::Area:
mLightAreaShapeItem->setText(1, lcLight::GetAreaShapeString(LightAreaShape));
mLightAreaShapeItem->setData(0, PropertyValueRole, static_cast<int>(LightAreaShape));
mLightAreaGridXItem->setText(1, QString::number(AreaGrid.x));
mLightAreaGridXItem->setData(0, PropertyValueRole, AreaGrid.x);
mLightAreaGridYItem->setText(1, QString::number(AreaGrid.y));
mLightAreaGridYItem->setData(0, PropertyValueRole, AreaGrid.y);
break;
case lcLightType::Count:
break;
}
mLightNameItem->setText(1, Name);
mLightNameItem->setData(0, PropertyValueRole, QVariant::fromValue(Name));
}
void lcQPropertiesTree::SetMultiple()

View file

@ -36,7 +36,8 @@ public:
enum
{
PropertyTypeRole = Qt::UserRole,
PropertyValueRole
PropertyValueRole,
PropertyRangeRole
};
enum PropertyType
@ -44,9 +45,12 @@ public:
PropertyGroup,
PropertyBool,
PropertyFloat,
PropertyInteger,
PropertyStep,
PropertyString,
PropertyStringList,
PropertyColor,
PropertyPieceColor,
PropertyPart
};
@ -55,12 +59,14 @@ protected slots:
void slotReturnPressed();
void slotSetValue(int value);
void slotColorButtonClicked();
void LightColorButtonClicked();
protected:
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void drawRow(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void updateColorEditor(QPushButton *editor, int value) const;
void UpdateLightColorEditor(QPushButton* Editor, QColor Color) const;
QTreeWidgetItem *addProperty(QTreeWidgetItem *parent, const QString& label, PropertyType propertyType);
@ -70,49 +76,68 @@ protected:
void SetLight(lcObject* Focus);
void SetMultiple();
void getPartProperties(lcPartProperties *properties);
lcLightType mLightType;
lcPropertyWidgetMode mWidgetMode;
lcObject* mFocus;
lcQPropertiesTreeDelegate *m_delegate;
lcQPropertiesTreeDelegate* mDelegate;
QIcon m_expandIcon;
QIcon m_checkedIcon;
QIcon m_uncheckedIcon;
QTreeWidgetItem *partPosition;
QTreeWidgetItem *partPositionX;
QTreeWidgetItem *partPositionY;
QTreeWidgetItem *partPositionZ;
QTreeWidgetItem *partRotation;
QTreeWidgetItem *partRotationX;
QTreeWidgetItem *partRotationY;
QTreeWidgetItem *partRotationZ;
QTreeWidgetItem *partVisibility;
QTreeWidgetItem *partShow;
QTreeWidgetItem *partHide;
QTreeWidgetItem *partAppearance;
QTreeWidgetItem *partColor;
QTreeWidgetItem *partID;
QTreeWidgetItem* mPieceAttributesItem;
QTreeWidgetItem* partVisibility;
QTreeWidgetItem* partShow;
QTreeWidgetItem* partHide;
QTreeWidgetItem* partAppearance;
QTreeWidgetItem* mPieceColorItem;
QTreeWidgetItem* mPieceIdItem;
QTreeWidgetItem *cameraPosition;
QTreeWidgetItem *cameraPositionX;
QTreeWidgetItem *cameraPositionY;
QTreeWidgetItem *cameraPositionZ;
QTreeWidgetItem *cameraTarget;
QTreeWidgetItem *cameraTargetX;
QTreeWidgetItem *cameraTargetY;
QTreeWidgetItem *cameraTargetZ;
QTreeWidgetItem *cameraUp;
QTreeWidgetItem *cameraUpX;
QTreeWidgetItem *cameraUpY;
QTreeWidgetItem *cameraUpZ;
QTreeWidgetItem *cameraSettings;
QTreeWidgetItem *cameraOrtho;
QTreeWidgetItem *cameraFOV;
QTreeWidgetItem *cameraNear;
QTreeWidgetItem *cameraFar;
QTreeWidgetItem *cameraName;
QTreeWidgetItem* cameraPosition;
QTreeWidgetItem* cameraPositionX;
QTreeWidgetItem* cameraPositionY;
QTreeWidgetItem* cameraPositionZ;
QTreeWidgetItem* cameraTarget;
QTreeWidgetItem* cameraTargetX;
QTreeWidgetItem* cameraTargetY;
QTreeWidgetItem* cameraTargetZ;
QTreeWidgetItem* cameraUp;
QTreeWidgetItem* cameraUpX;
QTreeWidgetItem* cameraUpY;
QTreeWidgetItem* cameraUpZ;
QTreeWidgetItem* mCameraAttributesItem;
QTreeWidgetItem* mCameraProjectionItem;
QTreeWidgetItem* cameraFOV;
QTreeWidgetItem* cameraNear;
QTreeWidgetItem* cameraFar;
QTreeWidgetItem* mCameraNameItem;
QTreeWidgetItem* mLightColorItem;
QTreeWidgetItem* mLightPowerItem;
QTreeWidgetItem* mLightAttributesItem;
QTreeWidgetItem* mLightTypeItem;
QTreeWidgetItem* mLightAttenuationDistanceItem;
QTreeWidgetItem* mLightAttenuationPowerItem;
QTreeWidgetItem* mLightSpotConeAngleItem;
QTreeWidgetItem* mLightSpotPenumbraAngleItem;
QTreeWidgetItem* mLightSpotTightnessItem;
QTreeWidgetItem* mLightAreaShapeItem;
QTreeWidgetItem* mLightAreaGridXItem;
QTreeWidgetItem* mLightAreaGridYItem;
QTreeWidgetItem* mLightSizeXItem;
QTreeWidgetItem* mLightSizeYItem;
QTreeWidgetItem* mLightNameItem;
QTreeWidgetItem* mLightCastShadowItem;
QTreeWidgetItem* mPositionItem;
QTreeWidgetItem* mPositionXItem;
QTreeWidgetItem* mPositionYItem;
QTreeWidgetItem* mPositionZItem;
QTreeWidgetItem* mRotationItem;
QTreeWidgetItem* mRotationXItem;
QTreeWidgetItem* mRotationYItem;
QTreeWidgetItem* mRotationZItem;
};
class lcQPropertiesTreeDelegate : public QItemDelegate
@ -161,4 +186,3 @@ private:
mutable QWidget *m_editedWidget;
mutable bool m_disablePainting;
};

View file

@ -348,14 +348,6 @@ void lcRenderDialog::on_RenderButton_clicked()
break;
}
/*
if (!LGEOPath.isEmpty())
{
Arguments.append(QString::fromLatin1("+L%1lg/").arg(LGEOPath));
Arguments.append(QString::fromLatin1("+L%1ar/").arg(LGEOPath));
}
*/
QString POVRayPath;
#ifdef Q_OS_WIN
@ -372,6 +364,29 @@ void lcRenderDialog::on_RenderButton_clicked()
POVRayPath = QDir::cleanPath(QCoreApplication::applicationDirPath() + QLatin1String("/povray"));
#endif
const QString POVRayDir = QFileInfo(POVRayPath).absolutePath();
const QString IncludePath = QDir::cleanPath(POVRayDir + "/include");
if (QFileInfo(IncludePath).exists())
Arguments.append(QString("+L\"%1\"").arg(IncludePath));
const QString IniPath = QDir::cleanPath(POVRayDir + "/ini");
if (QFileInfo(IniPath).exists())
Arguments.append(QString("+L\"%1\"").arg(IniPath));
if (lcGetActiveProject()->GetModels()[0]->GetPOVRayOptions().UseLGEO) {
const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH);
if (QFileInfo(LGEOPath).exists())
{
const QString LgPath = QDir::cleanPath(LGEOPath + "/lg");
if (QFileInfo(LgPath).exists())
Arguments.append(QString("+L\"%1\"").arg(LgPath));
const QString ArPath = QDir::cleanPath(LGEOPath + "/ar");
if (QFileInfo(ArPath).exists())
Arguments.append(QString("+L\"%1\"").arg(ArPath));
const QString StlPath = QDir::cleanPath(LGEOPath + "/stl");
if (QFileInfo(StlPath).exists())
Arguments.append(QString("+L\"%1\"").arg(StlPath));
}
}
mProcess = new lcRenderProcess(this);
#ifdef Q_OS_LINUX
connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(ReadStdErr()));
@ -882,11 +897,16 @@ void lcRenderDialog::on_OutputBrowseButton_clicked()
void lcRenderDialog::on_RenderOutputButton_clicked()
{
const QString RenderType = mCommand == POVRAY_RENDER ? QLatin1String("POV-Ray") : QLatin1String("Blender");
QFileInfo FileInfo(GetStdOutFileName());
QFileInfo FileInfo(GetStdErrFileName());
QString Message = tr("POV-Ray standard error file not found: %1.").arg(FileInfo.absoluteFilePath());
if (mCommand == BLENDER_RENDER)
{
FileInfo.setFile(GetStdOutFileName());
Message = tr("Blender standard output file not found: %1.").arg(FileInfo.absoluteFilePath());
}
if (!FileInfo.exists())
{
QMessageBox::warning(this, tr("Error"), tr("%1 Standard output file not found: %2.").arg(RenderType).arg(FileInfo.absoluteFilePath()));
QMessageBox::warning(this, tr("Error"), Message);
return;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 720 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

View file

@ -5602,7 +5602,7 @@ Informace o tom, jak stáhnout a nainstalovat knihovnu, naleznete na adrese http
</message>
<message>
<location filename="../common/lc_model.cpp" line="3957"/>
<source>New SpotLight</source>
<source>New Spotlight</source>
<translation>Nový zdroj osvětlení</translation>
</message>
<message>

View file

@ -5501,7 +5501,7 @@ Bitte lesen sie unter https://www.leocad.org nach wie man eine Bibliothek herunt
</message>
<message>
<location filename="../common/lc_model.cpp" line="3957"/>
<source>New SpotLight</source>
<source>New Spotlight</source>
<translation>Neues Scheinwerferlicht</translation>
</message>
<message>

View file

@ -5577,7 +5577,7 @@ Por favor, visita https://www.leocad.org para saber cómo descargar e instalar u
</message>
<message>
<location filename="../common/lc_model.cpp" line="3957"/>
<source>New SpotLight</source>
<source>New Spotlight</source>
<translation>nuevo foco</translation>
</message>
<message>

View file

@ -5485,7 +5485,7 @@ SVP visitez https://www.leocad.org pour apprendre comment télécharger et insta
</message>
<message>
<location filename="../common/lc_model.cpp" line="3957"/>
<source>New SpotLight</source>
<source>New Spotlight</source>
<translation>Nouvelle lumière projecteur</translation>
</message>
<message>

View file

@ -5412,7 +5412,7 @@ Veja https://www.leocad.org para saber como descarragar e instalar uma bibliotec
</message>
<message>
<location filename="../common/lc_model.cpp" line="3957"/>
<source>New SpotLight</source>
<source>New Spotlight</source>
<translation>Novo Projector</translation>
</message>
<message>

View file

@ -5477,7 +5477,7 @@ Please visit https://www.leocad.org for information on how to download and insta
</message>
<message>
<location filename="../common/lc_model.cpp" line="3957"/>
<source>New SpotLight</source>
<source>New Spotlight</source>
<translation type="unfinished"></translation>
</message>
<message>